Skip to content

@inbounds overrides val variable in macros. Wrong usage of local #54417

@0x0f0f0f

Description

@0x0f0f0f

It took me a while when debugging a compiled pattern symbolics matcher to realize why pattern variables i've named val were overridden by other values. I've ended up adding a prefix to those symbols to avoid the issue. The macro shouldn't be escaped, as fresh symbols are needed to avoid clashes.

julia> macro foo(x,i)
           v = [1,2,3,4,5]
           quote
               val = $x
               t = @inbounds ($v)[$i]
               println(val)
           end
       end

julia> @foo(2,3)
3

The reason is because

macro inbounds(blk)
    return Expr(:block,
        Expr(:inbounds, true),
        Expr(:local, Expr(:(=), :val, esc(blk))),
        Expr(:inbounds, :pop),
        :val)
end

My intuition was always that nested macro calls that "access" the same symbol, should hygiene the symbol in the innermost macro expansion, but it seems it's not the case. What's the correct pattern of macro hygiene for these cases? shall I file a PR renaming that val in @inbounds to something less likely to clash with outer identifiers?

julia> @macroexpand @foo(2,3)
quote
    #= REPL[39]:4 =#
    var"#9332#val" = 2
    #= REPL[39]:5 =#
    var"#9333#t" = begin
            $(Expr(:inbounds, true))
            local var"#9332#val" = ([1, 2, 3, 4, 5])[3]
            $(Expr(:inbounds, :pop))
            var"#9332#val"
        end
    #= REPL[39]:6 =#
    Main.println(var"#9332#val")
end
julia> versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8a (2024-03-01 10:14 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, tigerlake)
Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores)
Environment:
  JULIA_EDITOR = code
  JULIA_NUM_THREADS = 

Installed via juliaup

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