Error messages: https://discourse.julialang.org/t/improving-error-messages-for-the-scoping-problem/16209.
Remember, the local/global decision for variables does not happen at runtime, it happens at compile-time (I think early in lowering?). I think Stefan’s solution is to follow unconditional @goto
and always follow both branches (even for literal if false
). So it would fix the following example:
julia> dead=true;
julia> let
@show dead
@goto skip
dead = false
@label skip
end
ERROR: UndefVarError: dead not defined
but not
julia> dead=true;
julia> let
@show dead
if true @goto skip end
dead = false
@label skip
end
ERROR: UndefVarError: dead not defined
The rule would be: Follow all pathes (without evaluating known conditionals). If there exists a write before read path, then the variable defaults to local. Otherwise, it defaults to global.
As a side note: The while
gets evaluated in the outer scope, not the inner scope. That is probably confusing for some people as well:
julia> m=4; n=2; i=1; while i>0
i = n
@show i, n
global m -= 1
global n -= 1
@show m,n
m>0 || break
end; @show m, n, i
(i, n) = (2, 2)
(m, n) = (3, 1)
(i, n) = (1, 1)
(m, n) = (2, 0)
(i, n) = (0, 0)
(m, n) = (1, -1)
(i, n) = (-1, -1)
(m, n) = (0, -2)
(m, n, i) = (0, -2, 1)
So, regardless of this scoping, a minimally invasive (very non-optimizing) @code_semilowered
that produces valid julia source code with only let
blocks and @goto
would be nice for that. It would also teach people about the iterator interface.