Skip to content

Macro symbols are qualified or unqualified depending where they appear (struct & export example) #40490

@mobius-eng

Description

@mobius-eng

Started as a question on Discourse

The issue seem to happen in macros being instantiated inside other macros. Here is an example (from Discourse):

macro make_struct(arg)
    quote
        struct $(esc(arg))
            x
        end
        export $(esc(arg))
    end
end

const structs_to_make = [:Foo, :Bar]

macro make_many_structs()
    quote
        $([:(@make_struct $(st)) for st in structs_to_make]...)
    end
end

@make_struct by itself works fine:

julia> @macroexpand  @make_struct(xxxx)
quote
    #= REPL[1]:3 =#
    struct xxxx
        #= REPL[1]:4 =#
        x
    end
    #= REPL[1]:6 =#
    export xxxx
end

But invocation of @make_many_structs produces erroneous code in struct definition by qualifying the symbols:

julia> @macroexpand @make_many_structs
quote
    #= REPL[3]:3 =#
    begin
        #= REPL[1]:3 =#
        struct Main.Foo
            #= REPL[1]:4 =#
            x
        end
        #= REPL[1]:6 =#
        export Foo
    end
    begin
        #= REPL[1]:3 =#
        struct Main.Bar
            #= REPL[1]:4 =#
            x
        end
        #= REPL[1]:6 =#
        export Bar
    end
end

If $(st) in @make_many_structs is replaced by escaped interpolation, $(esc(st)), the expansion produces correct symbol for structs but incorrect for export:

<...>
export $(Expr(:escape, :Foo))
<...>

Julia version:

Julia Version 1.6.0-rc3
Commit 23267f0d46 (2021-03-16 17:04 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, skylake)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions