Skip to content

Commit

Permalink
Rollup merge of rust-lang#116086 - estebank:issue-115992, r=compiler-…
Browse files Browse the repository at this point in the history
…errors

More accurate suggestion for `self.` and `Self::`

Detect that we can't suggest `self.` in an associated function without `&self` receiver.

Partially address rust-lang#115992.

r? `@compiler-errors`
  • Loading branch information
matthiaskrgr authored Sep 23, 2023
2 parents ac5646a + 7d8559a commit 0850444
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 35 deletions.
58 changes: 34 additions & 24 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
module: None,
}
} else {
let mut span_label = None;
let item_span = path.last().unwrap().ident.span;
let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 {
debug!(?self.diagnostic_metadata.current_impl_items);
Expand All @@ -224,32 +225,41 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
&& let FnKind::Fn(_, _, sig, ..) = fn_kind
&& let Some(items) = self.diagnostic_metadata.current_impl_items
&& let Some(item) = items.iter().find(|i| {
if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind
&& i.ident.name == item_str.name
// don't suggest if the item is in Fn signature arguments
// issue #112590
i.ident.name == item_str.name
// Don't suggest if the item is in Fn signature arguments (#112590).
&& !sig.span.contains(item_span)
{
debug!(?item_str.name);
return true
}
false
})
{
let self_sugg = match &item.kind {
AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => "self.",
_ => "Self::",
};

Some((
item_span.shrink_to_lo(),
match &item.kind {
AssocItemKind::Fn(..) => "consider using the associated function",
AssocItemKind::Const(..) => "consider using the associated constant",
_ => unreachable!("item kind was filtered above"),
},
self_sugg.to_string()
))
let sp = item_span.shrink_to_lo();
match &item.kind {
AssocItemKind::Fn(fn_)
if !sig.decl.has_self() && fn_.sig.decl.has_self() => {
// Ensure that we only suggest `self.` if `self` is available,
// you can't call `fn foo(&self)` from `fn bar()` (#115992).
// We also want to mention that the method exists.
span_label = Some((
item.ident.span,
"a method by that name is available on `Self` here",
));
None
}
AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => Some((
sp,
"consider using the method on `Self`",
"self.".to_string(),
)),
AssocItemKind::Fn(_) => Some((
sp,
"consider using the associated function on `Self`",
"Self::".to_string(),
)),
AssocItemKind::Const(..) => Some((
sp,
"consider using the associated constant on `Self`",
"Self::".to_string(),
)),
_ => None
}
} else {
None
};
Expand Down Expand Up @@ -314,7 +324,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
msg: format!("cannot find {expected} `{item_str}` in {mod_prefix}{mod_str}"),
fallback_label,
span: item_span,
span_label: None,
span_label,
could_be_expr: false,
suggestion,
module,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
struct Foo {
field: u32,
}

impl Foo {
fn field(&self) -> u32 {
self.field
}

fn new() -> Foo {
field; //~ ERROR cannot find value `field` in this scope
Foo { field } //~ ERROR cannot find value `field` in this scope
}
}
fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0425]: cannot find value `field` in this scope
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:11:9
|
LL | fn field(&self) -> u32 {
| ----- a method by that name is available on `Self` here
...
LL | field;
| ^^^^^ a field by this name exists in `Self`

error[E0425]: cannot find value `field` in this scope
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:12:15
|
LL | fn field(&self) -> u32 {
| ----- a method by that name is available on `Self` here
...
LL | Foo { field }
| ^^^^^ a field by this name exists in `Self`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0425`.
2 changes: 1 addition & 1 deletion tests/ui/resolve/issue-103474.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ error[E0425]: cannot find function `first` in this scope
LL | first()
| ^^^^^ not found in this scope
|
help: consider using the associated function
help: consider using the method on `Self`
|
LL | self.first()
| +++++
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/resolve/issue-2356.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ error[E0425]: cannot find function `static_method` in this scope
LL | static_method();
| ^^^^^^^^^^^^^ not found in this scope
|
help: consider using the associated function
help: consider using the associated function on `Self`
|
LL | Self::static_method();
| ++++++
Expand Down Expand Up @@ -102,7 +102,7 @@ error[E0425]: cannot find function `grow_older` in this scope
LL | grow_older();
| ^^^^^^^^^^ not found in this scope
|
help: consider using the associated function
help: consider using the associated function on `Self`
|
LL | Self::grow_older();
| ++++++
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/self/class-missing-self.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ error[E0425]: cannot find function `sleep` in this scope
LL | sleep();
| ^^^^^ not found in this scope
|
help: consider using the associated function
help: consider using the method on `Self`
|
LL | self.sleep();
| +++++
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/suggestions/assoc-const-without-self.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0425]: cannot find value `A_CONST` in this scope
LL | A_CONST
| ^^^^^^^ not found in this scope
|
help: consider using the associated constant
help: consider using the associated constant on `Self`
|
LL | Self::A_CONST
| ++++++
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/suggestions/assoc_fn_without_self.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,12 @@ impl S {
bar(); //~ ERROR cannot find function `bar` in this scope
baz(2, 3); //~ ERROR cannot find function `baz` in this scope
}
fn d(&self) {
fn c() {
foo(); //~ ERROR cannot find function `foo` in this scope
}
foo(); //~ ERROR cannot find function `foo` in this scope
bar(); //~ ERROR cannot find function `bar` in this scope
baz(2, 3); //~ ERROR cannot find function `baz` in this scope
}
}
49 changes: 43 additions & 6 deletions tests/ui/suggestions/assoc_fn_without_self.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,76 @@ error[E0425]: cannot find function `foo` in this scope
LL | foo();
| ^^^ not found in this scope
|
help: consider using the associated function
help: consider using the associated function on `Self`
|
LL | Self::foo();
| ++++++

error[E0425]: cannot find function `bar` in this scope
--> $DIR/assoc_fn_without_self.rs:17:9
|
LL | fn bar(&self) {}
| --- a method by that name is available on `Self` here
...
LL | bar();
| ^^^ not found in this scope

error[E0425]: cannot find function `baz` in this scope
--> $DIR/assoc_fn_without_self.rs:18:9
|
LL | baz(2, 3);
| ^^^ not found in this scope
|
help: consider using the associated function on `Self`
|
LL | Self::baz(2, 3);
| ++++++

error[E0425]: cannot find function `foo` in this scope
--> $DIR/assoc_fn_without_self.rs:14:13
|
LL | foo();
| ^^^ not found in this scope

error[E0425]: cannot find function `foo` in this scope
--> $DIR/assoc_fn_without_self.rs:24:9
|
LL | foo();
| ^^^ not found in this scope
|
help: consider using the associated function on `Self`
|
LL | Self::foo();
| ++++++

error[E0425]: cannot find function `bar` in this scope
--> $DIR/assoc_fn_without_self.rs:25:9
|
LL | bar();
| ^^^ not found in this scope
|
help: consider using the associated function
help: consider using the method on `Self`
|
LL | self.bar();
| +++++

error[E0425]: cannot find function `baz` in this scope
--> $DIR/assoc_fn_without_self.rs:18:9
--> $DIR/assoc_fn_without_self.rs:26:9
|
LL | baz(2, 3);
| ^^^ not found in this scope
|
help: consider using the associated function
help: consider using the associated function on `Self`
|
LL | Self::baz(2, 3);
| ++++++

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

error: aborting due to 4 previous errors
error: aborting due to 8 previous errors

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

0 comments on commit 0850444

Please sign in to comment.