How unique are `gensym` symbols?

The documentation for gensym says that this function

generates a symbol which will not conflict with other variable names (in the same module).

When playing around with it, I get the impression that the symbols are actually globally unique:

julia> gensym()
Symbol("##277")

julia> @eval Base gensym()
Symbol("##278")

julia> module A end; @eval A gensym()
Symbol("##279")

Can I assume that gensym returns globally unique symbols?

The motivation for my question is that I want to manually sanitize an expression returned by a macro (and that contains itself a macro call). I can explain that in more detail if anybody is interested. The key point is that I want to get a symbol that doesn’t conflict with any identifier in the module where my macro is called. However, gensym would only guarantee that for the module containing the definition of my macro. I’ve figured out already that something like

newsym = @eval __module__ gensym()

inside the macro definition wouldn’t work because for nested macro calls, __module__ is not the module of the immediate caller, but that of the top level call site.

The note about a module is incorrect and will be fixed in v1.14. What’s really going on is that these names are globally unique within a julia session. However, precompilation of packages provides a mechanism by which names from different sessions can be imported into new sessions.

This means that e.g. if you made a package

module MyPackage

x = gensym()

end

and then you precompiled MyPackage, you could end up in a situation where

julia> using MyPackage

julia> MyPkackage.x == gensym()
true
1 Like

See also Precompiled gensyms are not unique · Issue #44903 · JuliaLang/julia for more details. It’s a bit of a footgun.