Skip to content
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

More accurate suggestion for self. and Self:: #116086

Merged
merged 4 commits into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`.
Loading