Commit f1b0b01
authored
Fix scope of hoisted signature-local variables (#56712)
When we declare inner methods, e.g. the `f` in
```
function fs()
f(lhs::Integer) = 1
f(lhs::Integer, rhs::(local x=Integer; x)) = 2
return f
end
```
we must hoist the definition of the (appropriately mangled) generic
function `f` to top-level, including all variables that were used in the
signature definition of `f`. This situation is a bit unique in the
language because it uses inner function scope, but gets executed in
toplevel scope. For example, you're not allowed to use a local of the
inner function in the signature definition:
```
julia> function fs()
local x=Integer
f(lhs::Integer, rhs::x) = 2
return f
end
ERROR: syntax: local variable x cannot be used in closure declaration
Stacktrace:
[1] top-level scope
@ REPL[3]:1
```
In particular, the restriction is signature-local:
```
julia> function fs()
f(rhs::(local x=Integer; x)) = 1
f(lhs::Integer, rhs::x) = 2
return f
end
ERROR: syntax: local variable x cannot be used in closure declaration
Stacktrace:
[1] top-level scope
@ REPL[4]:1
```
There's a special intermediate form `moved-local` that gets generated
for this definition. In c6c3d72, this
form stopped getting generated for certain inner methods. I suspect this
happened because of the incorrect assumption that the set of moved
locals is being computed over all signatures, rather than being a
per-signature property.
The result of all of this was that this is one of the few places where
lowering still generated a symbol as the lhs of an assignment for a
global (instead of globalref), because the code that generates the
assignment assumes it's a local, but the later pass doesn't know this.
Because we still retain the code for this from before we started using
globalref consistently, this wasn't generally causing a problems, except
possibly leaking a global (or potentially assigning to a global when
this wasn't intended). However, in follow on work, I want to make use of
knowing whether the LHS is a global or local in lowering, so this was
causing me trouble.
Fix all of this by putting back the `moved-local` where it was dropped.
Fixes #567111 parent 8ce7d0f commit f1b0b01
2 files changed
+9
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4279 | 4279 | | |
4280 | 4280 | | |
4281 | 4281 | | |
| 4282 | + | |
4282 | 4283 | | |
4283 | 4284 | | |
4284 | 4285 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4033 | 4033 | | |
4034 | 4034 | | |
4035 | 4035 | | |
| 4036 | + | |
| 4037 | + | |
| 4038 | + | |
| 4039 | + | |
| 4040 | + | |
| 4041 | + | |
| 4042 | + | |
| 4043 | + | |
0 commit comments