Commit 7a8cd6e
Remove :globaldecl and :global lowered forms; add Core.declare_global (JuliaLang#58279)
# Overview
In the spirit of JuliaLang#58187 and JuliaLang#57965, this PR lowers more surface syntax
to calls,
eliminating the lowered `:global` and `:globaldecl` operations in favour
of a
single `Core.declare_global` builtin.
`Core.declare_global` has the signature:
```
declare_global(module::Module, name::Symbol, strong::Bool=false, [ty::Type])
```
- When `strong = false`, it has the effect of `global name` at the top
level
(see the description for
[`PARTITION_KIND_DECLARED`](https://github.com/JuliaLang/julia/blob/d46b665067bd9fc352c89c9d0abb591eaa4f7695/src/julia.h#L706-L710)).
- With `strong = true`:
- No `ty` provided: if no global exists, creates a strong global with
type
`Any`. Has no effect if one already exists. This form is generated by
global assignments with no type declaration.
- `ty` provided: always creates a new global with the given type,
failing if
one already exists with a different declared type.
## Definition effects
One of the purposes of this change is to remove the definitions effects
for
`:global` and `:globaldecl`:
https://github.com/JuliaLang/julia/blob/d46b665067bd9fc352c89c9d0abb591eaa4f7695/src/method.c#L95-L105
The eventual goal is to make all the definition effects for a method
explicit
after lowering, simplifying interpreters for lowered IR.
## Minor lowering changes
### `global` permitted in more places
Adds a new ephemeral syntax head, `unused-only`, to wrap expressions
whose
result should not be used. It generates the `misplaced "global"
declaration`
error, and is slightly more forgiving than the old restriction. This was
necessary to permit `global` to be lowered in all contexts. Old:
```
julia> global example
julia> begin
global example
end
ERROR: syntax: misplaced "global" declaration
Stacktrace:
[1] top-level scope
@ REPL[2]:1
```
New:
```
julia> global example
julia> begin
global example
end
```
### `global` always lowered
This change maintains support for some expressions that cannot be
produced by
the parser (similar to `Expr(:const, :foo)`):
https://github.com/JuliaLang/julia/blob/d46b665067bd9fc352c89c9d0abb591eaa4f7695/test/precompile.jl#L2036
This used to work by bypassing lowering but is now lowered to the
appropriate
`declare_global` call.
## Generated functions
After lowering the body AST returned by a `@generated` function, the
definition
effects are still performed. Instead of relying on a check in
`jl_declare_global` to fail during this process, `GeneratedFunctionStub`
now
wraps the AST in a new Expr head, `Expr(:toplevel_pure, ...)`,
indicating
lowering should not produce toplevel side effects.
Currently, this is used only to omit calls to `declare_global` for
generated
functions, but it could also be used to improve the catch-all error
message when
lowering returns a thunk (telling the user if it failed because of a
closure,
generator, etc), or even to support some closures by making them opaque.
The error message for declaring a global as a side effect of a
`@generated`
function AST has changed, because it now fails when the assignment to an
undeclared global is performed. Old:
```
julia> @generated function foo(x)
:(global bar = x)
end
foo (generic function with 1 method)
julia> foo(1)
ERROR: new strong globals cannot be created in a generated function. Declare them outside using `global x::Any`.
Stacktrace:
[1] top-level scope
@ REPL[2]:1
```
New:
```
julia> @generated function foo(x)
:(global bar = x)
end
foo (generic function with 1 method)
julia> foo(1)
ERROR: Global Main.bar does not exist and cannot be assigned.
Note: Julia 1.9 and 1.10 inadvertently omitted this error check (JuliaLang#56933).
Hint: Declare it using `global bar` inside `Main` before attempting assignment.
Stacktrace:
[1] macro expansion
@ ./REPL[1]:1 [inlined]
[2] foo(x::Int64)
@ Main ./REPL[1]:1
[3] top-level scope
@ REPL[2]:1
```
## Examples of the new lowering
Toplevel weak global:
```
julia> Meta.@lower global example
:($(Expr(:thunk, CodeInfo(
1 ─ builtin Core.declare_global(Main, :example, false)
│ $(Expr(:latestworld))
└── return nothing
))))
```
Toplevel strong global declaration with type:
```
julia> Meta.@lower example::Int
:($(Expr(:thunk, CodeInfo(
1 ─ %1 = Main.example
│ %2 = Main.Int
│ %3 = builtin Core.typeassert(%1, %2)
└── return %3
))))
```
Toplevel strong global assignment:
```
julia> Meta.@lower example = 1
:($(Expr(:thunk, CodeInfo(
1 ─ builtin Core.declare_global(Main, :example, true)
│ $(Expr(:latestworld))
│ %3 = builtin Core.get_binding_type(Main, :example)
│ #s1 = 1
│ %5 = #s1
│ %6 = builtin %5 isa %3
└── goto #3 if not %6
2 ─ goto #4
3 ─ %9 = #s1
└── #s1 = Base.convert(%3, %9)
4 ┄ %11 = #s1
│ dynamic Base.setglobal!(Main, :example, %11)
└── return 1
))))
```
Toplevel strong global assignment with type:
```
julia> Meta.@lower example::Int = 1
:($(Expr(:thunk, CodeInfo(
1 ─ %1 = Main.Int
│ builtin Core.declare_global(Main, :example, true, %1)
│ $(Expr(:latestworld))
│ %4 = builtin Core.get_binding_type(Main, :example)
│ #s1 = 1
│ %6 = #s1
│ %7 = builtin %6 isa %4
└── goto #3 if not %7
2 ─ goto #4
3 ─ %10 = #s1
└── #s1 = Base.convert(%4, %10)
4 ┄ %12 = #s1
│ dynamic Base.setglobal!(Main, :example, %12)
└── return 1
))))
```
Global assignment inside function (call to `declare_global` hoisted to
top
level):
```
julia> Meta.@lower function f1(x)
global example = x
end
:($(Expr(:thunk, CodeInfo(
1 ─ $(Expr(:method, :(Main.f1)))
│ $(Expr(:latestworld))
│ $(Expr(:latestworld))
│ builtin Core.declare_global(Main, :example, false)
│ $(Expr(:latestworld))
│ builtin Core.declare_global(Main, :example, true)
│ $(Expr(:latestworld))
│ %8 = Main.f1
│ %9 = dynamic Core.Typeof(%8)
│ %10 = builtin Core.svec(%9, Core.Any)
│ %11 = builtin Core.svec()
│ %12 = builtin Core.svec(%10, %11, $(QuoteNode(:(#= REPL[7]:1 =#))))
│ $(Expr(:method, :(Main.f1), :(%12), CodeInfo(
@ REPL[7]:2 within `unknown scope`
1 ─ %1 = x
│ %2 = builtin Core.get_binding_type(Main, :example)
│ @_3 = %1
│ %4 = @_3
│ %5 = builtin %4 isa %2
└── goto #3 if not %5
2 ─ goto #4
3 ─ %8 = @_3
└── @_3 = Base.convert(%2, %8)
4 ┄ %10 = @_3
│ dynamic Base.setglobal!(Main, :example, %10)
└── return %1
)))
│ $(Expr(:latestworld))
│ %15 = Main.f1
└── return %15
))))
```
---------
Co-authored-by: Jameson Nash <[email protected]>1 parent a7b8f0c commit 7a8cd6e
File tree
18 files changed
+123
-147
lines changed- Compiler/src
- ssair
- base
- docs
- src
- test
18 files changed
+123
-147
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3457 | 3457 | | |
3458 | 3458 | | |
3459 | 3459 | | |
3460 | | - | |
3461 | | - | |
| 3460 | + | |
3462 | 3461 | | |
3463 | | - | |
3464 | | - | |
3465 | 3462 | | |
3466 | 3463 | | |
3467 | 3464 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
584 | 584 | | |
585 | 585 | | |
586 | 586 | | |
587 | | - | |
| 587 | + | |
588 | 588 | | |
589 | 589 | | |
590 | 590 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
| 28 | + | |
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
24 | | - | |
25 | 23 | | |
26 | 24 | | |
27 | 25 | | |
| |||
52 | 50 | | |
53 | 51 | | |
54 | 52 | | |
55 | | - | |
56 | 53 | | |
57 | 54 | | |
58 | 55 | | |
| |||
124 | 121 | | |
125 | 122 | | |
126 | 123 | | |
127 | | - | |
128 | 124 | | |
129 | 125 | | |
130 | 126 | | |
| |||
149 | 145 | | |
150 | 146 | | |
151 | 147 | | |
152 | | - | |
| 148 | + | |
153 | 149 | | |
154 | 150 | | |
155 | 151 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2758 | 2758 | | |
2759 | 2759 | | |
2760 | 2760 | | |
| 2761 | + | |
| 2762 | + | |
| 2763 | + | |
| 2764 | + | |
| 2765 | + | |
| 2766 | + | |
| 2767 | + | |
| 2768 | + | |
| 2769 | + | |
| 2770 | + | |
| 2771 | + | |
2761 | 2772 | | |
2762 | 2773 | | |
2763 | 2774 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1833 | 1833 | | |
1834 | 1834 | | |
1835 | 1835 | | |
1836 | | - | |
| 1836 | + | |
1837 | 1837 | | |
1838 | 1838 | | |
1839 | 1839 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
264 | 264 | | |
265 | 265 | | |
266 | 266 | | |
267 | | - | |
268 | 267 | | |
269 | 268 | | |
270 | 269 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1518 | 1518 | | |
1519 | 1519 | | |
1520 | 1520 | | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
1521 | 1538 | | |
1522 | 1539 | | |
1523 | 1540 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6460 | 6460 | | |
6461 | 6461 | | |
6462 | 6462 | | |
6463 | | - | |
6464 | | - | |
6465 | | - | |
6466 | | - | |
6467 | | - | |
6468 | | - | |
6469 | | - | |
6470 | | - | |
6471 | | - | |
6472 | | - | |
6473 | | - | |
6474 | | - | |
6475 | | - | |
6476 | | - | |
6477 | | - | |
6478 | | - | |
6479 | | - | |
6480 | 6463 | | |
6481 | 6464 | | |
6482 | 6465 | | |
| |||
0 commit comments