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

Type signature abbreviation in method error sometimes hides the information you need to know why it doesn't match #52113

Open
oxinabox opened this issue Nov 10, 2023 · 6 comments
Labels
error handling Handling of exceptions by Julia or the user REPL Julia's REPL (Read Eval Print Loop)

Comments

@oxinabox
Copy link
Contributor

Consider for example:

struct Foo{A, B, C} end
bar(::Foo{Tuple{Int}}) = 1
bar(::Foo{Tuple{Float64}}) = 1

bar(Foo{Tuple{Char,Int,Char,Char,Char,Char,Char,Char,Char,Char,Int, Char,Int,Char,Char,Char,Char,Char,Char,Char,Char,Int, Char,Int,Char,Char,Char,Char,Char,Char,Char,Char,Int, Char}, Dict{Int, Dict{Int,  Dict{Int,  Dict{Int,  Dict{Int,  Dict{Int,  Dict{Int,  Dict{Int, Int}}}}}}}}, Dict{Int, Dict{Int, Dict{Int, Int}}}}())

This is a method error becuase the first arguement is some giant tuple mixing Char and Int,
and there are only methods for if it was a 1-tuple of Int, or of Float64.
The key info you need to find what has gone wrong in your code is that first type parameter.
However, because of type abbreviation in the display of method errors, you do not always see that.
In this case the error is

ERROR: MethodError: no method matching bar(::Foo{Tuple{…}, Dict{…}, Dict{…}})

Closest candidates are:
  bar(::Foo{Tuple{Float64}})
   @ Main REPL[3]:1
  bar(::Foo{Tuple{Int64}})
   @ Main REPL[2]:1

We can't tell what is wrong with the Tuple type param, since its parameters are hidden.
(show(err) does make this display fully as you would hope. in my real world example though show(err) resulted in enough text being displayed from my stacktrace that my terminal started glitching)

As I understand it, the logic in type-signature abbreviation is such that any type parameters that are required to hit the particular dispatch are shown.
That makes sense for display in stacktraces -- you can know why a particular path was followed.
But that logic does not work for MethodError. For method error we want to see enough info to know why no existing method was hit.

I propose that, for now, we should not abbreviate type signatures in method errors,
until we can work out suitable logic for their abbreviation.

@oscardssmith oscardssmith added REPL Julia's REPL (Read Eval Print Loop) error handling Handling of exceptions by Julia or the user labels Nov 10, 2023
@oxinabox
Copy link
Contributor Author

@timholy basically I am proposing we revert #50809
pending working out a better way of determining which things we can abbreviate.

@rafaqz
Copy link
Contributor

rafaqz commented Jan 4, 2024

I just hit this too. We should be able to modify the amount of abbreviation until its not longer ambiguous what the problem is given the available method signature?

@timholy
Copy link
Member

timholy commented Jan 23, 2024

Why can't one do this:

julia> struct Foo{A, B, C} end

julia> bar(::Foo{Tuple{Int}}) = 1
bar (generic function with 1 method)

julia> bar(::Foo{Tuple{Float64}}) = 1
bar (generic function with 2 methods)

julia> bar(Foo{Tuple{Char,Int,Char,Char,Char,Char,Char,Char,Char,Char,Int, Char,Int,Char,Char,Char,Char,Char,Char,Char,Char,Int, Char,Int,Char,Char,Char,Char,Char,Char,Char,Char,Int, Char}, Dict{Int, Dict{Int,  Dict{Int,  Dict{Int,  Dict{Int,  Dict{Int,  Dict{Int,  Dict{Int, Int}}}}}}}}, Dict{Int, Dict{Int, Dict{Int, Int}}}}())
ERROR: MethodError: no method matching bar(::Foo{Tuple{…}, Dict{…}, Dict{…}})

Closest candidates are:
  bar(::Foo{Tuple{Float64}})
   @ Main REPL[3]:1
  bar(::Foo{Tuple{Int64}})
   @ Main REPL[2]:1

Stacktrace:
 [1] top-level scope
   @ REPL[4]:1
Some type information was truncated. Use `show(err)` to see complete types.

julia> show(err)
1-element ExceptionStack:
MethodError: no method matching bar(::Foo{Tuple{Char, Int64, Char, Char, Char, Char, Char, Char, Char, Char, Int64, Char, Int64, Char, Char, Char, Char, Char, Char, Char, Char, Int64, Char, Int64, Char, Char, Char, Char, Char, Char, Char, Char, Int64, Char}, Dict{Int64, Dict{Int64, Dict{Int64, Dict{Int64, Dict{Int64, Dict{Int64, Dict{Int64, Dict{Int64, Int64}}}}}}}}, Dict{Int64, Dict{Int64, Dict{Int64, Int64}}}})

Closest candidates are:
  bar(::Foo{Tuple{Float64}})
   @ Main REPL[3]:1
  bar(::Foo{Tuple{Int64}})
   @ Main REPL[2]:1

Stacktrace:
 [1] top-level scope
   @ REPL[4]:1

Prior discussion: #50803 (comment)

@timholy
Copy link
Member

timholy commented Jan 23, 2024

Ah, I just noticed that you anticipated this, @oxinabox:

(show(err) does make this display fully as you would hope. in my real world example though show(err) resulted in enough text being displayed from my stacktrace that my terminal started glitching)

But if we just revert #50809, your terminal will again glitch, no? So doesn't that leave us with:

@oxinabox
Copy link
Contributor Author

oxinabox commented Jan 23, 2024

The problem is show(err) not only shows the error message itself with this expanded,
But also shows the stacktrace with everything expanded -- which is 1-2 orders of magnitude more printing than just the error message.
It's printing the expanded stack trace that kills my terminal.

One option could be to have a way to control the expansion (or display at all) of the stacktrace separately from the error message.
Either with a separate function or a flag like show(err; stacktrace=false)
but that does have a discoverability problem, but we could maybe mention it in the error message for MethodError ?

@timholy
Copy link
Member

timholy commented Feb 16, 2024

Base.showerror(stdout, only(err.stack).exception) is a workaround for the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error handling Handling of exceptions by Julia or the user REPL Julia's REPL (Read Eval Print Loop)
Projects
None yet
Development

No branches or pull requests

4 participants