Global struct defined in some local scopes / what *is* top level?

Struct definitions nested in macros or methods throw an error explaining they need to be at top level. Top level is generally explained as the module’s global scope, but it’s evidently not (example below). Furthermore, the struct names escape the local scope unlike other local variables, behaving as if they were defined in the global scope. Does anyone know a rigorous definition of top level that takes into account how it dips into some local scopes (afaik: let, for, while, try, struct)?

julia> let
        struct X end
        x = X()
       end
X()

julia> X
X

julia> x
ERROR: UndefVarError: x not defined

julia> for i in 1
        struct Y end
        y = Y()
       end

julia> Y
Y

julia> y
ERROR: UndefVarError: y not defined

julia> macro blah()
        struct X end
        1
       end
ERROR: syntax: "struct" expression not at top level
Stacktrace:
 [1] top-level scope
   @ REPL[11]:1

julia> function blah()
        struct X end
        1
       end
ERROR: syntax: "struct" expression not at top level
Stacktrace:
 [1] top-level scope
   @ REPL[12]:1
1 Like
  1. let always create hard local scope
  2. function and type definition always evaluated at (module) top level

combined these two you get what you see here

1 Like

except for nested method definitions, perhaps

you mean closure?

Yes, semantically at least. I suppose the nested method is actually implemented as a functor in the local scope while the method with some modifications is hoisted to top level.

The above comments don’t seem very helpful to your original question.

Fwiw, I’m surprised too. For example, in the case of the struct defined in the let scope, it’s still surprising to me that it’s definition escapes the scope of this block. Clearly top level and module scope mean different things, and until now I’d assumed them to be the same.