Julia: Making introspection macros work for broadcasting syntax (`.`)

Created on 12 Aug 2018  ยท  7Comments  ยท  Source: JuliaLang/julia

julia> versioninfo()
Julia Version 1.0.0
Commit 5d4eaca0c9 (2018-08-08 20:58 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.0 (ORCJIT, haswell)
Environment:
  JULIA_EDITOR = code

julia> @which abs.([1,2,3])
ERROR: no unique matching method found for the specified argument types
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] which(::Any, ::Any) at ./reflection.jl:922
 [3] top-level scope at none:0

julia> @code_lowered abs.([1,2,3])
0-element Array{Union{Nothing, CodeInfo},1}

In the code above I'd expect @which to return broadcast and @code_lowered to return whatever code that broadcast gets lowered to.

If the loop fusion magic behind the scenes turns out to be complicated to work with these macros, clearer error messages (or, in the case of @code_lowered, an error message), would be great as well.

broadcast error handling

Most helpful comment

I know this is an old thread, but the introspection you're after is Meta.@lower:

julia> Meta.@lower abs.([1,2,3])
:($(Expr(:thunk, CodeInfo(
 1 โ”€ %1 = (Base.getproperty)(Base.Broadcast, :materialize)                   โ”‚
 โ”‚   %2 = (Base.getproperty)(Base.Broadcast, :broadcasted)                   โ”‚
 โ”‚   %3 = (Base.vect)(1, 2, 3)                                               โ”‚
 โ”‚   %4 = (%2)(abs, %3)                                                      โ”‚
 โ”‚   %5 = (%1)(%4)                                                           โ”‚
 โ””โ”€โ”€      return %5                                                          โ”‚
))))

That'll give you the breadcrumbs you wanted. Note that it's a complicated expansion โ€” there are two function calls there (well three including vect for the [1,2,3] literal) โ€” which do you want to introspect? If we just showed you Broadcast.materialize(bc::Base.Broadcast.Broadcasted) without giving you any more information about what it's argument was, it'd be similarly unhelpful.

I'm not sure we can really do much here. Perhaps the @which|@code_*|@edit macros could error and suggest Meta.@lower for expressions containing dots or other more complicated syntaxes.

All 7 comments

A workaround is to wrap in another function:

julia> f() = abs.([1,2,3])
f (generic function with 1 method)

julia> @code_lowered f()
CodeInfo(
1 1 โ”€ %1 = Base.Broadcast.materialize                                                 โ”‚
  โ”‚   %2 = Base.Broadcast.broadcasted                                                 โ”‚
  โ”‚   %3 = (Base.vect)(1, 2, 3)                                                       โ”‚
  โ”‚   %4 = (%2)(Main.abs, %3)                                                         โ”‚
  โ”‚   %5 = (%1)(%4)                                                                   โ”‚
  โ””โ”€โ”€      return %5                                                                  โ”‚
)

Yeah, that works for some macros like @code_*. Unfortunately it doesn't help for macros that give you information about the outermost method called, like @which:

julia> foo() = abs.([1,2,3])
foo (generic function with 2 methods)

julia> @which foo()
foo() in Main at REPL[76]:1

For broadcasting it is not completely clear what function should be shown due to e.g. fusing. In sin.(x .+ y) would you expect @which to show sin? It is a bit missleading since the function is executed is actually usually more something like (x, y) -> sin(x + y). I guess materialize could always be shown but that is a bit pointless.

I was encountering this error when I tried to dig into and understand the broadcasting mechanism, so in that case, showing the initial broadcast call would've been useful. Or the call to copy if that comes first, I'm still getting familiar with the broadcasting system.

I know this is an old thread, but the introspection you're after is Meta.@lower:

julia> Meta.@lower abs.([1,2,3])
:($(Expr(:thunk, CodeInfo(
 1 โ”€ %1 = (Base.getproperty)(Base.Broadcast, :materialize)                   โ”‚
 โ”‚   %2 = (Base.getproperty)(Base.Broadcast, :broadcasted)                   โ”‚
 โ”‚   %3 = (Base.vect)(1, 2, 3)                                               โ”‚
 โ”‚   %4 = (%2)(abs, %3)                                                      โ”‚
 โ”‚   %5 = (%1)(%4)                                                           โ”‚
 โ””โ”€โ”€      return %5                                                          โ”‚
))))

That'll give you the breadcrumbs you wanted. Note that it's a complicated expansion โ€” there are two function calls there (well three including vect for the [1,2,3] literal) โ€” which do you want to introspect? If we just showed you Broadcast.materialize(bc::Base.Broadcast.Broadcasted) without giving you any more information about what it's argument was, it'd be similarly unhelpful.

I'm not sure we can really do much here. Perhaps the @which|@code_*|@edit macros could error and suggest Meta.@lower for expressions containing dots or other more complicated syntaxes.

I get the same error for @code_llvm:

I have to wrap the broadcast calls inside a function. Calling the broadcast directly results in an error.

x=rand(10)
sinm(x) = sin.(x)

@code_llvm sinm(x)
@code_llvm sin.(x)

Error:

julia> @code_llvm sin.(x)
ERROR: no unique matching method found for the specified argument types
Stacktrace:
 [1] error(::String) at .\error.jl:33
 [2] which(::Any, ::Any) at .\reflection.jl:1148
 [3] _dump_function(::Any, ::Any, ::Bool, ::Bool, ::Bool, ::Bool, ::Symbol, ::Bool, ::Symbol, ::Base.CodegenParams) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.4\InteractiveUtils\src\codeview.jl:77
 [4] _dump_function at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.4\InteractiveUtils\src\codeview.jl:71 [inlined]
 [5] code_llvm at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.4\InteractiveUtils\src\codeview.jl:132 [inlined]
 [6] #code_llvm#28 at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.4\InteractiveUtils\src\codeview.jl:134 [inlined]
 [7] code_llvm(::Any, ::Any; raw::Bool, dump_module::Bool, optimize::Bool, debuginfo::Symbol) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.4\InteractiveUtils\src\codeview.jl:136
 [8] code_llvm(::Any, ::Any) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.4\InteractiveUtils\src\codeview.jl:136
 [9] top-level scope at none:0
Was this page helpful?
0 / 5 - 0 ratings