Description
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.