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

Show closest matching methods on MethodError #7686

Closed
jhasse opened this issue Jul 21, 2014 · 14 comments
Closed

Show closest matching methods on MethodError #7686

jhasse opened this issue Jul 21, 2014 · 14 comments

Comments

@jhasse
Copy link
Contributor

jhasse commented Jul 21, 2014

Hi! Often I run into no method matching errors without knowing what I'm passing wrong. To demonstrate with an example:

julia> function foo(l::Clong, i::Integer)
       println("$l $i")
       end
foo (generic function with 1 method)

julia> foo(0, 0)
ERROR: `foo` has no method matching foo(::Int64, ::Int64)

julia> foo(convert(Clong, 0), 0)
0 0

The error doesn't tell me which argument can't be implicitly converted.

The following in C gives me a better error message:

struct SomeType {};

void foo(SomeType, int) {
}

int main() {
    foo(1, 2);
}
test.cpp:10:13: error: could not convert '1' from 'int' to 'SomeType'
     foo(1, 2);
             ^
@JeffBezanson JeffBezanson changed the title "no method matching" should tell which argument can't be converted "no method matching" should tell which argument doesn't match Jul 21, 2014
@simonster
Copy link
Member

There are no implicit conversions in Julia method dispatch, and with multiple dispatch which argument doesn't match is not always well-defined. For example, given:

f(x::Float64, y::Float64) = ...
f(x::Int, y::Int) = ...

which argument doesn't match for f(::Float64, ::Int)? Still, it would be helpful to print the "closest" extant methods on MethodErrors, if we can come up with a metric. Related to #7512.

@JeffBezanson
Copy link
Member

closing as dup of #7512.

@ivarne
Copy link
Member

ivarne commented Jul 22, 2014

This is not a dup of #7512. This issue is about automatically suggesting different methods on the same function ordered by some measure of similarity. #7512 is about manually collecting a list of ambiguous and unexpectedly named functions as kind of an extension of the manual.

@simonster simonster changed the title "no method matching" should tell which argument doesn't match Show closest matching methods on MethodError Jul 22, 2014
@jhasse
Copy link
Contributor Author

jhasse commented Jul 23, 2014

I'm working on my idea I descriped here: #7512 (comment)

@ivarne
Copy link
Member

ivarne commented Jul 23, 2014

Great!

I'm not yet totally convinced, because I can't really see how you can add much value by ordering the methods differently than methods(fun) already do. When there isn't a method that matches, you will probably have to look at the full method table (or documentation) in order to find the right solution. It will be exiting to see what you come up with.

There is already (#4957) about colorizing the terminal display of a MethodTable, which should make it easier to read (if it ever is going to recover from the discussion about readability of different colors).

@jhasse
Copy link
Contributor Author

jhasse commented Jul 23, 2014

I'm using many typealiases and functions with a long signature. When I run into no method matching then it's very hard to find out what argument is wrong (I have to check every argument's type by myself). methods(fun) doesn't help me then, because it prints only one method anyway where ALL arguments are different to mine (because of typealiases).

@ivarne
Copy link
Member

ivarne commented Jul 23, 2014

Ok, the problem definitely changes when you have long signatures and typealiases. Maybe we could use custom ordering and some sort of equality highlighting when the missing method has 3 or more arguments?

@jhasse
Copy link
Contributor Author

jhasse commented Jul 23, 2014

Isn't that what I suggested in #7512 (comment)?

@ivarne
Copy link
Member

ivarne commented Jul 23, 2014

As far as I can tell, your f function in that comment has only two arguments.

@jhasse
Copy link
Contributor Author

jhasse commented Jul 23, 2014

Okay apart from only displaying it when the method has 3 or more arguments ;)
But even for methods with a short signature I think the more error info the better.

jhasse added a commit to jhasse/julia that referenced this issue Jul 23, 2014
@jhasse
Copy link
Contributor Author

jhasse commented Jul 23, 2014

Okay I've created a first patch which implements my idea. It's still very dirty and sorting isn't implemented. But apart from that it works :)
I will try to improve my patch in the next days before creating a PR. I'm still very new to Julia. Can someone tell me how I can hack on Julia's base library without having to invoke make on every change?

@ivarne
Copy link
Member

ivarne commented Jul 23, 2014

You can redefine functions, so if you have a file replhack.jl you can just include it with the new definition

# replhack.jl
function Base.showerror(io::IO, e::MethodError)
     # snip method content.
end

#testing
try
    foo(0,0)
catch e
    Base.showerror(STDIN, e)
end

When you are finished, you can copy the code into the base/replutils.jl and run make again

In this case the important thing is actually just to create a function that takes IO and a MethodError and test with that. The REPL does not show backtraces when errors are encountered in error displaying code, so that will be far less annoying.

@ivarne
Copy link
Member

ivarne commented Jul 23, 2014

You should also work on the latest master, as I changed this method when I merged #7688 earlier today. It will luckily be easy to copy your changes on top of mine.

jhasse added a commit to jhasse/julia that referenced this issue Jul 23, 2014
jhasse added a commit to jhasse/julia that referenced this issue Jul 24, 2014
jhasse added a commit to jhasse/julia that referenced this issue Jul 24, 2014
@jhasse
Copy link
Contributor Author

jhasse commented Jul 24, 2014

Thanks! I've used your replhack.jl to improve my patch.

I rebased against master and created a pull request :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants