Skip to content

Commit d175f11

Browse files
authored
Rollup merge of #149177 - chenyukang:yukang-fix-assoc-func-149038, r=estebank
Add proper suggestion for associated function with unknown field Fixes #149038 The first commit is changing the old suggestion to verbose, the second commit is a new added suggestion. r? ``@estebank``
2 parents b32845c + e802180 commit d175f11

14 files changed

+202
-77
lines changed

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3180,6 +3180,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31803180
err.span_label(within_macro_span, "due to this macro variable");
31813181
}
31823182

3183+
// Check if there is an associated function with the same name.
3184+
if let Some(def_id) = base_ty.peel_refs().ty_adt_def().map(|d| d.did()) {
3185+
for impl_def_id in self.tcx.inherent_impls(def_id) {
3186+
for item in self.tcx.associated_items(impl_def_id).in_definition_order() {
3187+
if let ExprKind::Field(base_expr, _) = expr.kind
3188+
&& item.name() == field.name
3189+
&& matches!(item.kind, ty::AssocKind::Fn { has_self: false, .. })
3190+
{
3191+
err.span_label(field.span, "this is an associated function, not a method");
3192+
err.note("found the following associated function; to be used as method, it must have a `self` parameter");
3193+
let impl_ty = self.tcx.type_of(impl_def_id).instantiate_identity();
3194+
err.span_note(
3195+
self.tcx.def_span(item.def_id),
3196+
format!("the candidate is defined in an impl for the type `{impl_ty}`"),
3197+
);
3198+
3199+
let ty_str = match base_ty.peel_refs().kind() {
3200+
ty::Adt(def, args) => self.tcx.def_path_str_with_args(def.did(), args),
3201+
_ => base_ty.peel_refs().to_string(),
3202+
};
3203+
err.multipart_suggestion(
3204+
"use associated function syntax instead",
3205+
vec![
3206+
(base_expr.span, ty_str),
3207+
(base_expr.span.between(field.span), "::".to_string()),
3208+
],
3209+
Applicability::MaybeIncorrect,
3210+
);
3211+
return err;
3212+
}
3213+
}
3214+
}
3215+
}
3216+
31833217
// try to add a suggestion in case the field is a nested field of a field of the Adt
31843218
let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
31853219
let (ty, unwrap) = if let ty::Adt(def, args) = base_ty.kind()

compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2511,7 +2511,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25112511
applicability = Applicability::HasPlaceholders;
25122512
"(...)".to_owned()
25132513
};
2514-
err.span_suggestion(
2514+
err.span_suggestion_verbose(
25152515
sugg_span,
25162516
"use associated function syntax instead",
25172517
format!("{ty_str}::{item_name}{args}"),

tests/ui/issues/issue-4265.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@ LL | struct Foo {
1414
| ---------- method `bar` not found for this struct
1515
...
1616
LL | Foo { baz: 0 }.bar();
17-
| ---------------^^^--
18-
| | |
19-
| | this is an associated function, not a method
20-
| help: use associated function syntax instead: `Foo::bar()`
17+
| ^^^ this is an associated function, not a method
2118
|
2219
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
2320
note: the candidate is defined in an impl for the type `Foo`
2421
--> $DIR/issue-4265.rs:6:5
2522
|
2623
LL | fn bar() {
2724
| ^^^^^^^^
25+
help: use associated function syntax instead
26+
|
27+
LL - Foo { baz: 0 }.bar();
28+
LL + Foo::bar();
29+
|
2830

2931
error: aborting due to 2 previous errors
3032

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
struct S;
2+
impl S {
3+
fn foo() {}
4+
fn bar(&self) {
5+
self.foo(); //~ ERROR no method named `foo` found for reference `&S` in the current scope
6+
let f: fn() = self.foo; //~ ERROR no field `foo` on type `&S`
7+
}
8+
}
9+
10+
fn main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error[E0599]: no method named `foo` found for reference `&S` in the current scope
2+
--> $DIR/assc-func-issue-149038.rs:5:14
3+
|
4+
LL | self.foo();
5+
| ^^^ this is an associated function, not a method
6+
|
7+
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
8+
note: the candidate is defined in an impl for the type `S`
9+
--> $DIR/assc-func-issue-149038.rs:3:5
10+
|
11+
LL | fn foo() {}
12+
| ^^^^^^^^
13+
help: use associated function syntax instead
14+
|
15+
LL - self.foo();
16+
LL + S::foo();
17+
|
18+
19+
error[E0609]: no field `foo` on type `&S`
20+
--> $DIR/assc-func-issue-149038.rs:6:28
21+
|
22+
LL | let f: fn() = self.foo;
23+
| ^^^
24+
| |
25+
| this is an associated function, not a method
26+
| unknown field
27+
|
28+
= note: found the following associated function; to be used as method, it must have a `self` parameter
29+
note: the candidate is defined in an impl for the type `S`
30+
--> $DIR/assc-func-issue-149038.rs:3:5
31+
|
32+
LL | fn foo() {}
33+
| ^^^^^^^^
34+
help: use associated function syntax instead
35+
|
36+
LL - let f: fn() = self.foo;
37+
LL + let f: fn() = S::foo;
38+
|
39+
40+
error: aborting due to 2 previous errors
41+
42+
Some errors have detailed explanations: E0599, E0609.
43+
For more information about an error, try `rustc --explain E0599`.

tests/ui/methods/issue-3707.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ error[E0599]: no method named `boom` found for reference `&Obj` in the current s
22
--> $DIR/issue-3707.rs:10:14
33
|
44
LL | self.boom();
5-
| -----^^^^--
6-
| | |
7-
| | this is an associated function, not a method
8-
| help: use associated function syntax instead: `Obj::boom()`
5+
| ^^^^ this is an associated function, not a method
96
|
107
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
118
note: the candidate is defined in an impl for the type `Obj`
129
--> $DIR/issue-3707.rs:6:5
1310
|
1411
LL | pub fn boom() -> bool {
1512
| ^^^^^^^^^^^^^^^^^^^^^
13+
help: use associated function syntax instead
14+
|
15+
LL - self.boom();
16+
LL + Obj::boom();
17+
|
1618

1719
error: aborting due to 1 previous error
1820

tests/ui/suggestions/issue-102354.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ error[E0599]: no method named `func` found for type `i32` in the current scope
22
--> $DIR/issue-102354.rs:9:7
33
|
44
LL | x.func();
5-
| --^^^^--
6-
| | |
7-
| | this is an associated function, not a method
8-
| help: use associated function syntax instead: `i32::func()`
5+
| ^^^^ this is an associated function, not a method
96
|
107
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
118
note: the candidate is defined in the trait `Trait`
129
--> $DIR/issue-102354.rs:2:5
1310
|
1411
LL | fn func() {}
1512
| ^^^^^^^^^
13+
help: use associated function syntax instead
14+
|
15+
LL - x.func();
16+
LL + i32::func();
17+
|
1618

1719
error: aborting due to 1 previous error
1820

tests/ui/suggestions/issue-103646.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ error[E0599]: no method named `nya` found for type parameter `T` in the current
44
LL | fn uwu<T: Cat>(c: T) {
55
| - method `nya` not found for this type parameter
66
LL | c.nya();
7-
| --^^^--
8-
| | |
9-
| | this is an associated function, not a method
10-
| help: use associated function syntax instead: `T::nya()`
7+
| ^^^ this is an associated function, not a method
118
|
129
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
1310
note: the candidate is defined in the trait `Cat`
1411
--> $DIR/issue-103646.rs:2:5
1512
|
1613
LL | fn nya() {}
1714
| ^^^^^^^^
15+
help: use associated function syntax instead
16+
|
17+
LL - c.nya();
18+
LL + T::nya();
19+
|
1820

1921
error: aborting due to 1 previous error
2022

tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ error[E0599]: no method named `test` found for struct `Box<Foo<i32>>` in the cur
22
--> $DIR/suggest-assoc-fn-call-deref.rs:13:7
33
|
44
LL | x.test();
5-
| --^^^^--
6-
| | |
7-
| | this is an associated function, not a method
8-
| help: use associated function syntax instead: `Foo::<i32>::test()`
5+
| ^^^^ this is an associated function, not a method
96
|
107
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
118
note: the candidate is defined in an impl for the type `Foo<T>`
129
--> $DIR/suggest-assoc-fn-call-deref.rs:8:5
1310
|
1411
LL | fn test() -> i32 { 1 }
1512
| ^^^^^^^^^^^^^^^^
13+
help: use associated function syntax instead
14+
|
15+
LL - x.test();
16+
LL + Foo::<i32>::test();
17+
|
1618

1719
error: aborting due to 1 previous error
1820

tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.stderr

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ LL | struct A {
55
| -------- method `foo` not found for this struct
66
...
77
LL | _a.foo();
8-
| ---^^^--
9-
| | |
10-
| | this is an associated function, not a method
11-
| help: use associated function syntax instead: `A::foo(_a)`
8+
| ^^^ this is an associated function, not a method
129
|
1310
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
1411
note: the candidate is defined in the trait `M`
1512
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:8:5
1613
|
1714
LL | fn foo(_a: Self);
1815
| ^^^^^^^^^^^^^^^^^
16+
help: use associated function syntax instead
17+
|
18+
LL - _a.foo();
19+
LL + A::foo(_a);
20+
|
1921

2022
error[E0599]: no method named `baz` found for struct `A` in the current scope
2123
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:23:8
@@ -24,17 +26,19 @@ LL | struct A {
2426
| -------- method `baz` not found for this struct
2527
...
2628
LL | _a.baz(0);
27-
| ---^^^---
28-
| | |
29-
| | this is an associated function, not a method
30-
| help: use associated function syntax instead: `A::baz(0)`
29+
| ^^^ this is an associated function, not a method
3130
|
3231
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
3332
note: the candidate is defined in the trait `M`
3433
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:10:5
3534
|
3635
LL | fn baz(_a: i32);
3736
| ^^^^^^^^^^^^^^^^
37+
help: use associated function syntax instead
38+
|
39+
LL - _a.baz(0);
40+
LL + A::baz(0);
41+
|
3842

3943
error[E0599]: no method named `bar` found for struct `A` in the current scope
4044
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:27:8
@@ -43,17 +47,19 @@ LL | struct A {
4347
| -------- method `bar` not found for this struct
4448
...
4549
LL | _b.bar();
46-
| ---^^^--
47-
| | |
48-
| | this is an associated function, not a method
49-
| help: use associated function syntax instead: `A::bar(_b)`
50+
| ^^^ this is an associated function, not a method
5051
|
5152
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
5253
note: the candidate is defined in the trait `M`
5354
--> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:9:5
5455
|
5556
LL | fn bar(_a: Self);
5657
| ^^^^^^^^^^^^^^^^^
58+
help: use associated function syntax instead
59+
|
60+
LL - _b.bar();
61+
LL + A::bar(_b);
62+
|
5763

5864
error: aborting due to 3 previous errors
5965

0 commit comments

Comments
 (0)