Skip to content

Add MethodError hints for functions in other modules #58715

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Keno
Copy link
Member

@Keno Keno commented Jun 12, 2025

When a MethodError occurs, check if functions with the same name exist
in other modules (particularly those of the argument types). This helps
users discover that they may need to import a function or ensure multiple
functions are the same generic function.

  • For Base functions: suggests importing (e.g., "You may have intended to import Base.length")
  • For other modules: suggests they may be intended as the same generic function
  • Shows all matches from relevant modules in sorted order
  • Uses modulesof! to properly handle all type structures including unions

Fixes #58682

When a MethodError occurs, check if functions with the same name exist
in other modules (particularly those of the argument types). This helps
users discover that they may need to import a function or ensure multiple
functions are the same generic function.

- For Base functions: suggests importing (e.g., "You may have intended to import Base.length")
- For other modules: suggests they may be intended as the same generic function
- Shows all matches from relevant modules in sorted order
- Uses modulesof! to properly handle all type structures including unions

Fixes #58682
@Keno Keno force-pushed the method-error-hints branch from c9f8fa5 to e90469b Compare June 12, 2025 01:49
@Keno
Copy link
Member Author

Keno commented Jun 12, 2025

(Written by claude code per #58666 - we should update AGENTS.md to tell the AI to do that).

print(io, "\nYou may have intended to import ")
show_unquoted(io, Expr(:., :Base, QuoteNode(name)))
# Check for functions with the same name in other modules
if f_is_function && isdefined(ft.name, :singletonname)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if f_is_function && isdefined(ft.name, :singletonname)
if f_is_function

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, yes, I'm on it - give a minute ;)

for mod in sorted_modules
if isdefined(mod, name)
candidate = getfield(mod, name)
if candidate !== f && (isa(candidate, Function) || isa(candidate, Type)) && hasmethod(candidate, arg_types)
Copy link
Member

@vtjnash vtjnash Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if candidate !== f && (isa(candidate, Function) || isa(candidate, Type)) && hasmethod(candidate, arg_types)
if candidate !== f && ex.world != typemax(UInt) && hasmethod(candidate, arg_types; world=ex.world)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes current behavior, but I agree that it should have checked in ex.world

Comment on lines +351 to +353
show_unquoted(io, Expr(:., nameof(f_module), QuoteNode(name)))
print(io, " and ")
show_unquoted(io, Expr(:., nameof(mod), QuoteNode(name)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look like they would print submodules very weirdly. I think you want

Suggested change
show_unquoted(io, Expr(:., nameof(f_module), QuoteNode(name)))
print(io, " and ")
show_unquoted(io, Expr(:., nameof(mod), QuoteNode(name)))
show_unquoted(io, Expr(:., f_module, QuoteNode(name)))
print(io, " and ")
show_unquoted(io, Expr(:., mod, QuoteNode(name)))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can print the full path. I figured you'd already know the full module path since it'd be in one the types that printed in the error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can just imagine some weird cases though, like "You may have intended Artifacts and Artifacts to be the same", neglecting to mention that one of those is Pkg.Artifacts 😂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that sounds convincing to me. I'll switch it to the full path.

print(io, "\nYou may have intended to import ")
show_unquoted(io, Expr(:., :Base, QuoteNode(name)))
else
print(io, "\nYou may have intended for ")
Copy link
Member

@vtjnash vtjnash Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know the use of the presumptive author "you" is pre-existing, but I don't think it is right to assert that the "you" here who might want this to have worked and the package author who intended for it to work are the same person. Should we word these with the package name as the subject instead?

Suggested change
print(io, "\nYou may have intended for ")
print(io, "\n$mod may have intended for ")

Or rather "The intent in $mod may have been to import $f_module: $name"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"The intent in $mod may have been to import $f_module: $name"

I think we've generally been try to warn people away from import. Maybe

"The definition in $mod by have intended to extend $f_module.$name"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vtjnash Thoughts on that wording?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to me. I tend to think import is fine and would be clear here, but not enough to try to convince other people that they need to use it

This comment was marked as spam.

@nsajko nsajko added the error messages Better, more actionable error messages label Jun 12, 2025
@Colour267

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error messages Better, more actionable error messages
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider ADL-like MethodError warning
4 participants