Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion JuliaLowering/src/macro_expansion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to change the LineNumberNode slightly (allows file === nothing), but I guess we don't use this in lowering right now.

Does this affect anything?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, as the file === nothing -> file = :none case above is just for passing line number nodes to buggy macros (buggy assuming file is generally allowed to be anything). We could try always normalizing file to string or symbol everywhere in lowering, but that would be hard to do completely since these things can be values as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the argument used though? it seems like macro expansion just drops it right now

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used in the expr-macro case

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
Expand Down
19 changes: 19 additions & 0 deletions JuliaLowering/test/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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