There is a problem with beginners and the global scope https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/223. Regardless of the eventual solution, it would be desirable to backport better error messages. A more primitive change would be https://github.com/JuliaLang/julia/pull/29585.
Below is a pretty rube-goldberg attempt that only works on debug builds of master (otherwise the relevant symbols from interpreter.c
for scanning the stacktrace are missing):
julia> function Base.showerror(io::IO, ex::UndefVarError, bt)
if ex.var in [:UTF16String, :UTF32String, :WString, :utf16, :utf32, :wstring, :RepString]
return showerror(io, ErrorException("""
`$(ex.var)` has been moved to the package LegacyStrings.jl:
Run Pkg.add("LegacyStrings") to install LegacyStrings on Julia v0.5-;
Then do `using LegacyStrings` to get `$(ex.var)`.
"""))
end
print(io, "UndefVarError: $(ex.var) not defined")
#check whether we have tried to find a global
global last_bt = bt
check_bt_for_errtype(io, ex, bt)
end
julia> function check_bt_for_errtype(io, ex, bt)
st = stacktrace(bt, true)
for sf in st
if sf.func == :jl_get_binding_or_error || sf.func == :jl_eval_global_var
print(io, "\nthe global variable $(ex.var) was not found. Did you mistype or forget a `where {$(ex.var)}` clause?")
return
end
end
print(io, "\nthe local variable $(ex.var) was accessed before assignment. Did you mean `global $(ex.var)`?")
nothing
end
With this we display in whether the failed resolution of the symbol was in the global scope or in a local scope:
julia> xxx
ERROR: UndefVarError: xxx not defined
the global variable xxx was not found. Did you mistype or forget a `where {xxx}` clause?
julia> f(x::T) = x
ERROR: UndefVarError: T not defined
the global variable T was not found. Did you mistype or forget a `where {T}` clause?
julia> struct flub
x::T
end
ERROR: UndefVarError: T not defined
the global variable T was not found. Did you mistype or forget a `where {T}` clause?
julia> f()=xxx
f (generic function with 1 method)
julia> f()
ERROR: UndefVarError: xxx not defined
the global variable xxx was not found. Did you mistype or forget a `where {xxx}` clause?
On the other hand:
julia> N=10;
julia> for i=1:N
N -= 1
end
ERROR: UndefVarError: N not defined
the local variable N was accessed before assignment. Did you mean `global N`?
julia> function ff()
return N
N=0
end
ff (generic function with 1 method)
julia> ff()
ERROR: UndefVarError: N not defined
the local variable N was accessed before assignment. Did you mean `global N`?
What do you all think? Is this the missing information for confused people?
It would be nice if we could remove the “or forget where {N}” clause in some contexts where we know that this definitely is not the case. It would be nice to also show in which module we tried to resolve a global symbol, and when offering " Did you mean global N
" it may be nice to check whether a global of that name actually exists.