diff --git a/JuliaLowering/src/macro_expansion.jl b/JuliaLowering/src/macro_expansion.jl index 2a4ef150daaa3..f88fa91915d96 100644 --- a/JuliaLowering/src/macro_expansion.jl +++ b/JuliaLowering/src/macro_expansion.jl @@ -335,7 +335,6 @@ function expand_macro(ctx, ex) # method was defined (may be different from `parentmodule(macfunc)`) mod_for_ast = lookup_method_instance(macfunc, macro_args, ctx.macro_world).def.module - expanded = fix_toplevel_expansion(ctx, expanded, mod_for_ast, macro_loc) new_layer = ScopeLayer(length(ctx.scope_layers)+1, mod_for_ast, current_layer_id(ctx), true) push_layer!(ctx, mod_for_ast, true) @@ -454,6 +453,9 @@ function expand_forms_1(ctx::MacroExpansionContext, ex::SyntaxTree) end elseif k == K"macrocall" expand_macro(ctx, ex) + elseif k == K"toplevel" && length(ctx.scope_layer_stack) > 1 + fix_toplevel_expansion(ctx, ex, current_layer(ctx).mod, + source_location(LineNumberNode, ex)) elseif k == K"module" || k == K"toplevel" || k == K"inert" # Remove scope layer information from any inert syntax which survives # macro expansion so that it doesn't contaminate lowering passes which diff --git a/JuliaLowering/test/macros.jl b/JuliaLowering/test/macros.jl index d92b3243a76b4..2c5c8008167b8 100644 --- a/JuliaLowering/test/macros.jl +++ b/JuliaLowering/test/macros.jl @@ -483,4 +483,23 @@ end @test_broken JuliaLowering.eval(test_mod, code) == ("outer x", "inner x") end +@testset "toplevel macro hygiene" begin + @eval test_mod global mod = $test_mod + @eval test_mod module MacroMod + global mod = MacroMod + macro escaped_toplevel() + esc(Expr(:toplevel, :(mod))) + end + macro inner_escaped_toplevel() + Expr(:toplevel, esc(:(mod))) + end + macro unescaped_toplevel() + Expr(:toplevel, :(mod)) + end + end + @test JuliaLowering.include_string(test_mod, "MacroMod.@escaped_toplevel") === test_mod + @test JuliaLowering.include_string(test_mod, "MacroMod.@inner_escaped_toplevel") === test_mod + @test JuliaLowering.include_string(test_mod, "MacroMod.@unescaped_toplevel") === test_mod.MacroMod +end + end