Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider some cleanup of macro-hygiene rules in global scope #53667

Open
Keno opened this issue Mar 8, 2024 · 0 comments
Open

Consider some cleanup of macro-hygiene rules in global scope #53667

Keno opened this issue Mar 8, 2024 · 0 comments
Labels
macros @macros
Milestone

Comments

@Keno
Copy link
Member

Keno commented Mar 8, 2024

Here's a fun quiz: What do these macros do:

module Mod
    macro set_x()
        :(x = 2)
    end
    macro set_x_global()
          :(global x = 2)
    end
    macro set_x_global2()
        :(global x; x = 3)
    end
    macro x()
        :(x)
    end
    macro x_global()
        :(global x; x)
    end
end

Here's the answer (assuming expansion in Main):

  • @set_x introduces (for every invocation of @set_x a different) gensym'd global in Main that acts as a psuedo-local (local in the sense that you don't know the name of it, so you can't name it)
  • @set_x_global sets the (escaped) global x in Main
  • @set_x_global2 declares the (escaped) global x in Main and then assigns the (non-gensymed) global x in Mod (not Main)
  • @x access the global x in Mod according to the ordinary hygiene rules (this is fine)
  • @x_global declares the (escaped) global x in Main and then does the same thing as @x.

This came up in the context of #53515. I discussed this today with @JeffBezanson and @vtjnash and our conclusions were basically as follows:

  1. The @set_x behavior is fine with the exception of leaking a bunch of unnamed globals, which can never be deleted (and fill up the symbol table and hold on to memory). The original justification for these psuedo locals was that toplevel expressions could not be placed inside toplevel begin/end blocks, but this restriction no longer exists as far as we can tell, so these can be local now.

  2. The behavior difference in @set_x_global and @set_x_global2 is unfortunate. In particular, having x in @set_x_global2 refer to two different globals is problematic. According to a strict interpretation of our macro hygiene rules, these should both be assigning globals in Mod (without the extra declaration of global Main.x).

  3. @x and @x_global are basically fine, again with the possible exception of the global Main.x)

We discussed that we should see if we can remedy point 1 right now. One of the primary things that would change is the renaming across Expr(:toplevel) as currently Expr(:toplevel, :(x=1), :x) uses the same gensym'd global in both arguments. However, this is already changing in #53515, so we might as well take advantage of that and try to do this properly.

Point 2 was considered too breaking by @JeffBezanson to do before 2.0, with the provisio that we should tell people not to write it (if you want Main.x write global $(esc(:x)) = 2, if you want Mod.x write global x; x = 3 or global $(GlobalRef(Mod, :x)) = 4). There was disagreement about whether to change the implicit global Main.x in @set_x_global2 and @x_global.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
macros @macros
Projects
None yet
Development

No branches or pull requests

1 participant