Missing field resolve error doesn't look at associated functions (original) (raw)

Code

// https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=0cc9d5eab0906c2323994ad5fa4358e5

struct S; impl S { fn foo() {} fn bar(&self) { self.foo(); let f: fn() = self.foo; } }

Current output

error[E0599]: no method named foo found for reference &S in the current scope --> src/lib.rs:5:14 | 5 | self.foo(); | -----^^^-- | | | | | this is an associated function, not a method | help: use associated function syntax instead: S::foo() | = note: found the following associated functions; to be used as methods, functions must have a self parameter note: the candidate is defined in an impl for the type S --> src/lib.rs:3:5 | 3 | fn foo() {} | ^^^^^^^^

error[E0609]: no field foo on type &S --> src/lib.rs:6:28 | 6 | let f: fn() = self.foo; | ^^^ unknown field

Desired output

error[E0599]: no method named foo found for reference &S in the current scope --> src/lib.rs:5:14 | 5 | self.foo(); | ^^^ this is an associated function, not a method | = note: found the following associated functions; to be used as methods, functions must have a self parameter note: the candidate is defined in an impl for the type S --> src/lib.rs:3:5 | 3 | fn foo() {} | ^^^^^^^^ help: use associated function syntax instead --> src/lib.rs:5:14 | 5 - self.foo(); 5 + Self::foo(); |

error[E0609]: no field foo on type &S --> src/lib.rs:6:28 | 6 | let f: fn() = self.foo; | ^^^ this is an associated function, not a method | = note: found the following associated functions; to be used as methods, functions must have a self parameter note: the candidate is defined in an impl for the type S --> src/lib.rs:3:5 | 3 | fn foo() {} | ^^^^^^^^ help: use associated function syntax instead --> src/lib.rs:5:14 | 6 - let f: fn() = self.foo; 6 + let f: fn() = Self::foo; |

Rationale and extra context

The structured suggestion should be verbose instead of inline, to make it clearer what we want the user to write.

The second case doesn't look for associated functions, because the syntax is quite far from what it needs to be, so it never occurred to us that there are cases where it is appropriate to do so. Sadly, this happens during resolve, so we are limited in how much we can explore the expression's context to figure out if an fn pointer is desired to begin with. On the other hand, this can be a two-fold typo, where someone wanted Self::foo() instead of self.foo and forgot the parentheses. The mention of the associated function should be the last fallback for field access resolve error, as it is the least likely thing the user intended.

Other cases

Rust Version

Build using the Nightly version: 1.93.0-nightly

(2025-11-16 518b428304e0008859cb)

Anything else?

Noted by https://social.linux.pizza/@jamesthebard/115566259453362334