-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Print a tip in MethodError #57339
base: master
Are you sure you want to change the base?
Print a tip in MethodError #57339
Conversation
# if the function has only one method, print a tip about the number of arguments to be used | ||
if f isa Function && length(methods(f)) == 1 | ||
print(io, "\n\nTip: the function `$f` was called with ", length(arg_types_param), " arguments, but has only one method accepting ", length(methods(f)[1].sig.parameters)-1, " argument.\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is quite right; f
doesn't need to be a function in order for there to be a mismatch in the number of arguments (i.e. it could be a type or callable object), but also, I believe this tip will be printed when the correct number of arguments is provided but the sole method does not apply to them. For example, consider:
julia> f(x::Int) = x + 1
f (generic function with 1 method)
julia> f("hi")
ERROR: MethodError: no method matching f(::String)
The function `f` exists, but no method is defined for this combination of argument types.
Closest candidates are:
f(::Int64)
@ Main REPL[1]:1
Stacktrace:
[1] top-level scope
@ REPL[2]:1
As currently implemented, the error message would include
Tip: the function `f` was called with 1 arguments, but has only one method accepting 1 argument.
which I don't think would help a user determine the source of the issue or how to fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is correct I didnt think about this. But could be easly resolved by also checking if the number of arguments with wich the function was called is different from the accepted arguments, like so:
if f isa Function && length(methods(f)) == 1 && length(arg_types_param) !== length(methods(f)[1].sig.parameters)-1
print(...)
end
can you think of other cases in wich this tip could be misleading?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good start but I don't think it will handle vararg signatures correctly. For example, consider:
julia> f(x::Int, y::Float64...) = x + sum(y; init=0.0)
f (generic function with 1 method)
julia> m = only(methods(f));
julia> nargs = length(m.sig.parameters) - 1 # number of defined arguments in the signature
2
julia> f(1) # provided arguments < nargs, no error
1.0
julia> f(1.0) # provided arguments < nargs but error is irrelevant to that
ERROR: MethodError: no method matching f(::Float64)
[...]
julia> f(1, 2) # provided arguments == nargs
ERROR: MethodError: no method matching f(::Int64, ::Int64)
[...]
julia> f(1, 2, 3) # provided arguments > nargs
ERROR: MethodError: no method matching f(::Int64, ::Int64, ::Int64)
[...]
You could use isvatuple(m.sig)
to identify this case.
If a function with only one method accepting a certain number of arguments, gets called with a different number of arguments, a Tip is printed in the MethodError like this:
See the original pull request and issue #56325