Skip to content

Commit 61b38b2

Browse files
authored
Rollup merge of #116086 - estebank:issue-115992, r=compiler-errors
More accurate suggestion for `self.` and `Self::` Detect that we can't suggest `self.` in an associated function without `&self` receiver. Partially address #115992. r? ``@compiler-errors``
2 parents 8c9e516 + 7d8559a commit 61b38b2

9 files changed

+126
-35
lines changed

compiler/rustc_resolve/src/late/diagnostics.rs

+34-24
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
214214
module: None,
215215
}
216216
} else {
217+
let mut span_label = None;
217218
let item_span = path.last().unwrap().ident.span;
218219
let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 {
219220
debug!(?self.diagnostic_metadata.current_impl_items);
@@ -224,32 +225,41 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
224225
&& let FnKind::Fn(_, _, sig, ..) = fn_kind
225226
&& let Some(items) = self.diagnostic_metadata.current_impl_items
226227
&& let Some(item) = items.iter().find(|i| {
227-
if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind
228-
&& i.ident.name == item_str.name
229-
// don't suggest if the item is in Fn signature arguments
230-
// issue #112590
228+
i.ident.name == item_str.name
229+
// Don't suggest if the item is in Fn signature arguments (#112590).
231230
&& !sig.span.contains(item_span)
232-
{
233-
debug!(?item_str.name);
234-
return true
235-
}
236-
false
237231
})
238232
{
239-
let self_sugg = match &item.kind {
240-
AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => "self.",
241-
_ => "Self::",
242-
};
243-
244-
Some((
245-
item_span.shrink_to_lo(),
246-
match &item.kind {
247-
AssocItemKind::Fn(..) => "consider using the associated function",
248-
AssocItemKind::Const(..) => "consider using the associated constant",
249-
_ => unreachable!("item kind was filtered above"),
250-
},
251-
self_sugg.to_string()
252-
))
233+
let sp = item_span.shrink_to_lo();
234+
match &item.kind {
235+
AssocItemKind::Fn(fn_)
236+
if !sig.decl.has_self() && fn_.sig.decl.has_self() => {
237+
// Ensure that we only suggest `self.` if `self` is available,
238+
// you can't call `fn foo(&self)` from `fn bar()` (#115992).
239+
// We also want to mention that the method exists.
240+
span_label = Some((
241+
item.ident.span,
242+
"a method by that name is available on `Self` here",
243+
));
244+
None
245+
}
246+
AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => Some((
247+
sp,
248+
"consider using the method on `Self`",
249+
"self.".to_string(),
250+
)),
251+
AssocItemKind::Fn(_) => Some((
252+
sp,
253+
"consider using the associated function on `Self`",
254+
"Self::".to_string(),
255+
)),
256+
AssocItemKind::Const(..) => Some((
257+
sp,
258+
"consider using the associated constant on `Self`",
259+
"Self::".to_string(),
260+
)),
261+
_ => None
262+
}
253263
} else {
254264
None
255265
};
@@ -314,7 +324,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
314324
msg: format!("cannot find {expected} `{item_str}` in {mod_prefix}{mod_str}"),
315325
fallback_label,
316326
span: item_span,
317-
span_label: None,
327+
span_label,
318328
could_be_expr: false,
319329
suggestion,
320330
module,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
struct Foo {
2+
field: u32,
3+
}
4+
5+
impl Foo {
6+
fn field(&self) -> u32 {
7+
self.field
8+
}
9+
10+
fn new() -> Foo {
11+
field; //~ ERROR cannot find value `field` in this scope
12+
Foo { field } //~ ERROR cannot find value `field` in this scope
13+
}
14+
}
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0425]: cannot find value `field` in this scope
2+
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:11:9
3+
|
4+
LL | fn field(&self) -> u32 {
5+
| ----- a method by that name is available on `Self` here
6+
...
7+
LL | field;
8+
| ^^^^^ a field by this name exists in `Self`
9+
10+
error[E0425]: cannot find value `field` in this scope
11+
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:12:15
12+
|
13+
LL | fn field(&self) -> u32 {
14+
| ----- a method by that name is available on `Self` here
15+
...
16+
LL | Foo { field }
17+
| ^^^^^ a field by this name exists in `Self`
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0425`.

tests/ui/resolve/issue-103474.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ error[E0425]: cannot find function `first` in this scope
1919
LL | first()
2020
| ^^^^^ not found in this scope
2121
|
22-
help: consider using the associated function
22+
help: consider using the method on `Self`
2323
|
2424
LL | self.first()
2525
| +++++

tests/ui/resolve/issue-2356.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ error[E0425]: cannot find function `static_method` in this scope
7373
LL | static_method();
7474
| ^^^^^^^^^^^^^ not found in this scope
7575
|
76-
help: consider using the associated function
76+
help: consider using the associated function on `Self`
7777
|
7878
LL | Self::static_method();
7979
| ++++++
@@ -102,7 +102,7 @@ error[E0425]: cannot find function `grow_older` in this scope
102102
LL | grow_older();
103103
| ^^^^^^^^^^ not found in this scope
104104
|
105-
help: consider using the associated function
105+
help: consider using the associated function on `Self`
106106
|
107107
LL | Self::grow_older();
108108
| ++++++

tests/ui/self/class-missing-self.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ error[E0425]: cannot find function `sleep` in this scope
1010
LL | sleep();
1111
| ^^^^^ not found in this scope
1212
|
13-
help: consider using the associated function
13+
help: consider using the method on `Self`
1414
|
1515
LL | self.sleep();
1616
| +++++

tests/ui/suggestions/assoc-const-without-self.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0425]: cannot find value `A_CONST` in this scope
44
LL | A_CONST
55
| ^^^^^^^ not found in this scope
66
|
7-
help: consider using the associated constant
7+
help: consider using the associated constant on `Self`
88
|
99
LL | Self::A_CONST
1010
| ++++++

tests/ui/suggestions/assoc_fn_without_self.rs

+8
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,12 @@ impl S {
1717
bar(); //~ ERROR cannot find function `bar` in this scope
1818
baz(2, 3); //~ ERROR cannot find function `baz` in this scope
1919
}
20+
fn d(&self) {
21+
fn c() {
22+
foo(); //~ ERROR cannot find function `foo` in this scope
23+
}
24+
foo(); //~ ERROR cannot find function `foo` in this scope
25+
bar(); //~ ERROR cannot find function `bar` in this scope
26+
baz(2, 3); //~ ERROR cannot find function `baz` in this scope
27+
}
2028
}

tests/ui/suggestions/assoc_fn_without_self.stderr

+43-6
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,76 @@ error[E0425]: cannot find function `foo` in this scope
44
LL | foo();
55
| ^^^ not found in this scope
66
|
7-
help: consider using the associated function
7+
help: consider using the associated function on `Self`
88
|
99
LL | Self::foo();
1010
| ++++++
1111

1212
error[E0425]: cannot find function `bar` in this scope
1313
--> $DIR/assoc_fn_without_self.rs:17:9
1414
|
15+
LL | fn bar(&self) {}
16+
| --- a method by that name is available on `Self` here
17+
...
18+
LL | bar();
19+
| ^^^ not found in this scope
20+
21+
error[E0425]: cannot find function `baz` in this scope
22+
--> $DIR/assoc_fn_without_self.rs:18:9
23+
|
24+
LL | baz(2, 3);
25+
| ^^^ not found in this scope
26+
|
27+
help: consider using the associated function on `Self`
28+
|
29+
LL | Self::baz(2, 3);
30+
| ++++++
31+
32+
error[E0425]: cannot find function `foo` in this scope
33+
--> $DIR/assoc_fn_without_self.rs:14:13
34+
|
35+
LL | foo();
36+
| ^^^ not found in this scope
37+
38+
error[E0425]: cannot find function `foo` in this scope
39+
--> $DIR/assoc_fn_without_self.rs:24:9
40+
|
41+
LL | foo();
42+
| ^^^ not found in this scope
43+
|
44+
help: consider using the associated function on `Self`
45+
|
46+
LL | Self::foo();
47+
| ++++++
48+
49+
error[E0425]: cannot find function `bar` in this scope
50+
--> $DIR/assoc_fn_without_self.rs:25:9
51+
|
1552
LL | bar();
1653
| ^^^ not found in this scope
1754
|
18-
help: consider using the associated function
55+
help: consider using the method on `Self`
1956
|
2057
LL | self.bar();
2158
| +++++
2259

2360
error[E0425]: cannot find function `baz` in this scope
24-
--> $DIR/assoc_fn_without_self.rs:18:9
61+
--> $DIR/assoc_fn_without_self.rs:26:9
2562
|
2663
LL | baz(2, 3);
2764
| ^^^ not found in this scope
2865
|
29-
help: consider using the associated function
66+
help: consider using the associated function on `Self`
3067
|
3168
LL | Self::baz(2, 3);
3269
| ++++++
3370

3471
error[E0425]: cannot find function `foo` in this scope
35-
--> $DIR/assoc_fn_without_self.rs:14:13
72+
--> $DIR/assoc_fn_without_self.rs:22:13
3673
|
3774
LL | foo();
3875
| ^^^ not found in this scope
3976

40-
error: aborting due to 4 previous errors
77+
error: aborting due to 8 previous errors
4178

4279
For more information about this error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)