Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UndefVarError for a struct type parameter #41728

Closed
aplavin opened this issue Jul 29, 2021 · 2 comments · Fixed by #51979
Closed

UndefVarError for a struct type parameter #41728

aplavin opened this issue Jul 29, 2021 · 2 comments · Fixed by #51979
Labels
error messages Better, more actionable error messages types and dispatch Types, subtyping and method dispatch

Comments

@aplavin
Copy link
Contributor

aplavin commented Jul 29, 2021

Not sure if that's the intended behaviour or not, but seems surprising:

julia> struct A{T}
               x::Vector{<:T}
       end

# ok:
julia> A([1, 2, 3])
A{Int64}([1, 2, 3])

# fails:
julia> A(Any[1, 2, 3])
ERROR: UndefVarError: T not defined

In my particular case, this code was a mistake anyway: I intended to write

struct A{T<:SomeSuperT}
    x::Vector{T}
end

instead. But maybe it is relevant in the wider context.

I'm using the latest julia release:

julia> versioninfo()
Julia Version 1.6.2
Commit 1b93d53fc4 (2021-07-14 15:36 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, skylake)
@JeffBezanson
Copy link
Sponsor Member

As you can probably guess, this struct definition creates a default constructor similar to the following function:

f(::Vector{<:T}) where T = T

During dispatch, we try to pick a value for T, given the argument types. But that cannot always be done --- the types of the arguments don't always imply a unique value for T. And in edge cases, it can be non-obvious whether the algorithm that picks a value for T will succeed. In this case:

julia> f(Int[])
Int64

julia> f(Any[])
ERROR: UndefVarError: T not defined

So with a concrete element type we assume that type is what we should pick. But it's not well-defined, since technically T could be any type greater than Int. Arguably we could make Any work here, since only one type is >: Any (Any itself).

@aplavin
Copy link
Contributor Author

aplavin commented Jul 30, 2021

It's not just an issue with Any, but with any abstract type: they all lead to T not defined. I don't know whether it makes sense to always infer T as the struct parameter, so that

julia> f(Int[])
Int64
julia> f(Any[])
Any
julia> f(Real[])
Real

But the current behavior is confusing: I thought that T declaration was missing somewhere in my struct definition, which turned out not to be the case. Maybe, this could be solved with a better error message without any changes to the result? I don't know if there are legitimate usecases of f(::Vector{<:T}) where T = T as opposed to f(::Vector{T}) where T = T.

@JeffBezanson JeffBezanson added the types and dispatch Types, subtyping and method dispatch label Jul 30, 2021
@vtjnash vtjnash added the error messages Better, more actionable error messages label Mar 29, 2022
vtjnash added a commit that referenced this issue Oct 31, 2023
Record the 'scope' of the variable that was undefined (the Module, or a
descriptive word such as :local or :static_parameter). Add that scope to
the error message, and expand the hint suggestions added by the REPL to
include more specific advice on common mistakes:

  - forgetting to set an initial value
  - forgetting to import a global
  - creating a local of the same name as a global
  - not matching a static parameter in a signature subtype

Fixes #17062 (although more could probably be done to search for typos using REPL.string_distance and getting the method from stacktrace)
Fixes #18877
Fixes #25263
Fixes #35126
Fixes #39280
Fixes #41728
Fixes #48731
Fixes #49917
Fixes #50369
vtjnash added a commit that referenced this issue Nov 8, 2023
Record the 'scope' of the variable that was undefined (the Module, or a
descriptive word such as :local or :static_parameter). Add that scope to
the error message, and expand the hint suggestions added by the REPL to
include more specific advice on common mistakes:

  - forgetting to set an initial value
  - forgetting to import a global
  - creating a local of the same name as a global
  - not matching a static parameter in a signature subtype

Fixes #17062 (although more could probably be done to search for typos using REPL.string_distance and getting the method from stacktrace)
Fixes #18877
Fixes #25263
Fixes #35126
Fixes #39280
Fixes #41728
Fixes #48731
Fixes #49917
Fixes #50369
@vtjnash vtjnash closed this as completed in 449c7a2 Nov 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error messages Better, more actionable error messages types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants