The MethodError message sometimes doesn’t make sense, and I’m not sure if it’s a problem with MethodError or the way it’s used.
For example the following fails (as documented in Measurements.jl):
julia> using SpecialFunctions, Measurements
julia> zeta(2.0 ± 0.1)
ERROR: MethodError: no method matching zeta(::Measurement{Float64})
Closest candidates are:
zeta(::Number) at /home/user/.julia/packages/SpecialFunctions/Bdhxh/src/gamma.jl:527
zeta(::Number, ::Number) at /home/user/.julia/packages/SpecialFunctions/Bdhxh/src/gamma.jl:547
zeta(::BigFloat) at /home/user/.julia/packages/SpecialFunctions/Bdhxh/src/gamma.jl:465
...
But note how the message is confusing, since there is a candidate zeta(::Number)
and
julia> Measurement{Float64} <: Number
true
The error comes from the following code in SpecialFunctions.jl:
function $f(z::Number)
x = float(z)
typeof(x) === typeof(z) && throw(MethodError($f, (z,)))
# There is nothing to fallback to, as this didn't change the argument types
$f(x)
end
My question: Is this an issue with Julia (MethodError
printing a message that assumes too much), or is it a semantically incorrect use of MethodError
?
Similar cases in the standard library
Sometimes ArgumentError
is used for example in base/abstractarray.jl
:
require_one_based_indexing(A...) = !has_offset_axes(A...) || throw(ArgumentError("offset arrays are not supported but got an array with index other than 1"))
and
checkindex(::Type{Bool}, inds::AbstractUnitRange, i) =
throw(ArgumentError("unable to check bounds for indices of type $(typeof(i))"))
These are helpful messages.
But in other places, MethodError
is used and leads to the same problem. For example in base/irrationals.jl
:
<(::Irrational{s}, ::Irrational{s}) where {s} = false
function <(x::AbstractIrrational, y::AbstractIrrational)
Float64(x) != Float64(y) || throw(MethodError(<, (x, y)))
return Float64(x) < Float64(y)
end
And in base/essentials.jl
:
function tuple_type_tail(T::Type)
...
T.name === Tuple.name || throw(MethodError(tuple_type_tail, (T,)))
...
end
This last one gives the following message, similarly confusing:
julia> Base.tuple_type_tail(Int32)
ERROR: MethodError: no method matching tuple_type_tail(::Type{Int32})
Closest candidates are:
tuple_type_tail(::Type) at essentials.jl:211
Stacktrace:
[1] tuple_type_tail(::Type) at ./essentials.jl:217
[2] top-level scope at REPL[56]:1
So, bad message or bad use of MethodError?