# Making method errors more helpful by indicating the defining module

**URL:** <https://discourse.julialang.org/t/making-method-errors-more-helpful-by-indicating-the-defining-module/10935>\
**Category:** Internals & Design\
**Created:** [May 16, 2018, 6:31pm UTC](https://discourse.julialang.org/t/making-method-errors-more-helpful-by-indicating-the-defining-module/10935 "2018-05-16T18:31:37Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [May 16, 2018, 6:31pm UTC](https://discourse.julialang.org/t/making-method-errors-more-helpful-by-indicating-the-defining-module/10935/1 "2018-05-16T18:31:37Z")

</div>

Currently, MethodErrors for missing methods do not print any information about the module to which the underlying function belongs. For example:

```julia
julia> module Bar
         f(x::Int) = 10
       end
Bar

julia> using .Bar: f

julia> f(10)
10

julia> f("hello")
ERROR: MethodError: no method matching f(::String)
Closest candidates are:
  f(::Int64) at REPL[1]:2

```

This can make it more difficult to determine exactly which function I should overload to fix the method error. Just looking at the error message, it would appear that defining `f(::String)` would be appropriate, but I actually need to define `Foo.f(::String)` or `import Foo: f; f(::String) = ...`.

The issue gets worse when method errors occur deeper in the code, as it can be pretty unclear what the originating module for a given function is.

To be clear, I’m not suggesting changing the language semantics at all, just the way we report errors.

I suspect that this would also help with a very common category of error for new users, which is failing to import `Base` methods. For example, a new user might do the following:

```julia
julia> module Foo

       struct Bar; end
       sort([Bar(), Bar()])
       end
ERROR: MethodError: no method matching isless(::Foo.Bar, ::Foo.Bar)

```

Given that error message, the natural thing to do is to define precisely what is suggested:

```julia
julia> module Foo

       struct Bar; end
       isless(::Bar, ::Bar) = true
       sort([Bar(), Bar()])
       end
WARNING: replacing module Foo
ERROR: MethodError: no method matching isless(::Foo.Bar, ::Foo.Bar)

```

but of course that doesn’t actually work.

If, instead, the MethodError printed `MethodError: no method matching Base.isless(::Foo.Bar, ::Foo.Bar)`, then we would at least be helping users towards the correct implementation:

```julia
julia> module Foo

       struct Bar; end
       Base.isless(::Bar, ::Bar) = true
       sort([Bar(), Bar()])
       end
WARNING: replacing module Foo
Foo

```

Method _ambiguity_ errors already show the function with its relevant module, so this is clearly possible. I’m happy to open a PR if this seems like a good idea.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [May 16, 2018, 6:37pm UTC](https://discourse.julialang.org/t/making-method-errors-more-helpful-by-indicating-the-defining-module/10935/2 "2018-05-16T18:37:00Z")

</div>

Yep, this sounds great!

Tangentially related: [https://github.com/JuliaLang/julia/pull/24299](https://github.com/JuliaLang/julia/pull/24299)

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [May 29, 2018, 10:01pm UTC](https://discourse.julialang.org/t/making-method-errors-more-helpful-by-indicating-the-defining-module/10935/3 "2018-05-29T22:01:49Z")

</div>

> [@rdeits](#):
>
> Method ambiguity errors already show the function with its relevant module, so this is clearly possible. I’m happy to open a PR if this seems like a good idea.

Yep. Tangentially related, it would be great to no longer have (at least) three different implementations of this with varying features. 😛
