LoadError in Macro on 0.7

I posted this to slack recently but didn’t find a solution. I’m trying to upgrade someone else’s package to 0.7, and I’m getting an error from a macro when I run tests. The issue is, I don’t really know how macros work, and can’t interpret the error. Pretty sure this is the macro causing the issue:

macro forward_func(ex, fs)
    T, field = ex.args[1], ex.args[2].args[1]
    T = esc(T)
    fs = isexpr(fs, :tuple) ? map(esc, fs.args) : [esc(fs)]
    :($([:($f(x::$T, args...) = (Base.@_inline_meta; $f(x.$field, args...)))
        for f in fs]...);
    nothing)
end

And the error when I try to test the package:

ERROR: LoadError: LoadError: LoadError: type QuoteNode has no field args
Stacktrace:
 [1] getproperty(::Any, ::Symbol) at ./sysimg.jl:18
 [2] @forward_func(::LineNumberNode, ::Module, ::Any, ::Any) at /Users/kev/.julia/dev/SpatialEcology/src/Commatrix_functions.jl:3
 [3] include at ./boot.jl:317 [inlined]
 [4] include_relative(::Module, ::String) at ./loading.jl:1034
 [5] include at ./sysimg.jl:29 [inlined]
 [6] include(::String) at /Users/kev/.julia/dev/SpatialEcology/src/SpatialEcology.jl:2
 [7] top-level scope at none:0
 [8] include at ./boot.jl:317 [inlined]
 [9] include_relative(::Module, ::String) at ./loading.jl:1034
 [10] include(::Module, ::String) at ./sysimg.jl:29
 [11] top-level scope at none:0
 [12] eval at ./boot.jl:319 [inlined]
 [13] eval(::Expr) at ./client.jl:394
 [14] top-level scope at ./none:3 [inlined]
 [15] top-level scope at ./<missing>:0
in expression starting at /Users/kev/.julia/dev/SpatialEcology/src/Commatrix_functions.jl:11
in expression starting at /Users/kev/.julia/dev/SpatialEcology/src/Commatrix_functions.jl:11
in expression starting at /Users/kev/.julia/dev/SpatialEcology/src/SpatialEcology.jl:29

I found this PR to fix a similar problem in a different package, but I’m not sure exactly how to apply it.

Someone on slack suggested trying to change fs.args to fs.value based on the PR I linked, but I still get the error. If I change ex.args[2].args[1] to ex.args[2].value[1], I instead get

ERROR: LoadError: LoadError: LoadError: MethodError: no method matching getindex(::Symbol, ::Int64)
Stacktrace:
 [1] @forward_func(::LineNumberNode, ::Module, ::Any, ::Any) at /Users/kev/.julia/dev/SpatialEcology/src/Commatrix_functions.jl:3
#...

Which suggests that’s where the issue is, but I could use some guidance on what to try next.

To debug things like this, I’d recommend using dump(ex) to see the structure of the expression being passed to the macro. That should help you understand what the structure is that it’s actually getting and from there you can probably figure out how the code needs to change to transform that structure into whatever the desired definition is.

1 Like

Alright, I added

@show dump(ex)
@show dump(ex.args[2].value)
@show ex.args[2].value

to the top of the function, and that returned:

Expr
  head: Symbol .
  args: Array{Any}((2,))
    1: Symbol Assmbl
    2: QuoteNode
      value: Symbol occ
dump(ex) = nothing
Symbol occ
dump((ex.args[2]).value) = nothing
(ex.args[2]).value = :occ

I changed the function to

macro forward_func(ex, fs)
    T, field = ex.args[1], ex.args[2].value

    T = esc(T)
    fs = isexpr(fs, :tuple) ? map(esc, fs.args) : [esc(fs)]
    :($([:($f(x::$T, args...) = (Base.@_inline_meta; $f(x.$field, args...)))
        for f in fs]...);
    nothing)
end

And this seems to get through that error at least. I don’t understand enough about macros to know if I broke it, but I guess I’ll just keep going until I actually make it to the tests :laughing: (I got a bunch of new dep warnings and a new unrelated error).