You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
lowering: Refactor lowering for const and typed globals
This is a prepratory commit for #54654 to change the lowering of
`const` and typed globals to be compatible with the new semantics.
Currently, we lower `const a::T = val` to:
```
const a
global a::T
a = val
```
(which further expands to typed-globals an implicit converts).
This works, because, under the hood, our const declarations
are actually assign-once globals. Note however, that this is
not syntactically reachable, since we have a parse error for
plain `const a`:
```
julia> const a
ERROR: ParseError:
# Error @ REPL[1]:1:1
const a
└─────┘ ── expected assignment after `const`
Stacktrace:
[1] top-level scope
@ none:1
```
However, this lowering is not atomic with respect to world age.
The semantics in #54654 require that the const-ness and the value
are established atomically (with respect to world age, potentially
on another thread) or undergo invalidation.
To resolve this issue, this PR changes the lowering of `const a::T = val` to:
```
let
local a::T = val
const (global a) = a
end
```
where the latter is a special syntax form `Expr(:const, GlobalRef(,:a), :a)`.
A similar change is made to const global declarations, which previously
lowered via intrinsic, i.e. `global a::T = val` lowered to:
```
global a
Core.set_binding_type!(Main, :a, T)
_T = Core.get_binding_type(Main, :a)
if !isa(val, _T)
val = convert(_T, val)
end
a = val
```
This changes the `set_binding_type!` to instead be a syntax form `Expr(:globaldecl, :a, T)`.
This is not technically required, but we currently do not use intrinsics for
world-age affecting side-effects anywhere else in the system. In particular, after #54654,
it would be illegal to call `set_binding_type!` in anything but top-level context.
Now, we have discussed in the past that there should potentially be intrinsic functions
for global modifications (method table additions, etc), currently only reachable through
`Core.eval`, but such an intrinsic would require semantics that differ from both
the current `set_binding_type!` and the new `:globaldecl`.
Using an Expr form here is the most consistent with our current practice for
these sort of things elsewhere and accordingly, this PR removes the intrinsic.
Note that this PR does not yet change any syntax semantics,
although there could in principle be a reordering of
side-effects within an expression (e.g. things like
`global a::(@isdefined(a) ? Int : Float64)` might behave
differently after this commit. However, we never defined
the order of side effects (which is part of what this is
cleaning up, although, I am not formally defining any specific
ordering here either - #54654 will do some of that), and that
is not a common case, so this PR should be largely considered
non-semantic with respect to the syntax change.
0 commit comments