1
Fork 0

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``
This commit is contained in:
Matthias Krüger 2023-09-24 01:14:06 +02:00 committed by GitHub
commit 61b38b216a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 128 additions and 37 deletions

View file

@ -214,6 +214,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
module: None, module: None,
} }
} else { } else {
let mut span_label = None;
let item_span = path.last().unwrap().ident.span; let item_span = path.last().unwrap().ident.span;
let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 { let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 {
debug!(?self.diagnostic_metadata.current_impl_items); debug!(?self.diagnostic_metadata.current_impl_items);
@ -224,32 +225,41 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
&& let FnKind::Fn(_, _, sig, ..) = fn_kind && let FnKind::Fn(_, _, sig, ..) = fn_kind
&& let Some(items) = self.diagnostic_metadata.current_impl_items && let Some(items) = self.diagnostic_metadata.current_impl_items
&& let Some(item) = items.iter().find(|i| { && let Some(item) = items.iter().find(|i| {
if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind i.ident.name == item_str.name
&& i.ident.name == item_str.name // Don't suggest if the item is in Fn signature arguments (#112590).
// don't suggest if the item is in Fn signature arguments
// issue #112590
&& !sig.span.contains(item_span) && !sig.span.contains(item_span)
{
debug!(?item_str.name);
return true
}
false
}) })
{ {
let self_sugg = match &item.kind { let sp = item_span.shrink_to_lo();
AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => "self.", match &item.kind {
_ => "Self::", AssocItemKind::Fn(fn_)
}; if !sig.decl.has_self() && fn_.sig.decl.has_self() => {
// Ensure that we only suggest `self.` if `self` is available,
Some(( // you can't call `fn foo(&self)` from `fn bar()` (#115992).
item_span.shrink_to_lo(), // We also want to mention that the method exists.
match &item.kind { span_label = Some((
AssocItemKind::Fn(..) => "consider using the associated function", item.ident.span,
AssocItemKind::Const(..) => "consider using the associated constant", "a method by that name is available on `Self` here",
_ => unreachable!("item kind was filtered above"), ));
}, None
self_sugg.to_string() }
)) 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 { } else {
None None
}; };
@ -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}"), msg: format!("cannot find {expected} `{item_str}` in {mod_prefix}{mod_str}"),
fallback_label, fallback_label,
span: item_span, span: item_span,
span_label: None, span_label,
could_be_expr: false, could_be_expr: false,
suggestion, suggestion,
module, module,

View file

@ -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() {}

View file

@ -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`.

View file

@ -19,7 +19,7 @@ error[E0425]: cannot find function `first` in this scope
LL | first() LL | first()
| ^^^^^ not found in this scope | ^^^^^ not found in this scope
| |
help: consider using the associated function help: consider using the method on `Self`
| |
LL | self.first() LL | self.first()
| +++++ | +++++

View file

@ -73,7 +73,7 @@ error[E0425]: cannot find function `static_method` in this scope
LL | static_method(); LL | static_method();
| ^^^^^^^^^^^^^ not found in this scope | ^^^^^^^^^^^^^ not found in this scope
| |
help: consider using the associated function help: consider using the associated function on `Self`
| |
LL | Self::static_method(); LL | Self::static_method();
| ++++++ | ++++++
@ -102,7 +102,7 @@ error[E0425]: cannot find function `grow_older` in this scope
LL | grow_older(); LL | grow_older();
| ^^^^^^^^^^ not found in this scope | ^^^^^^^^^^ not found in this scope
| |
help: consider using the associated function help: consider using the associated function on `Self`
| |
LL | Self::grow_older(); LL | Self::grow_older();
| ++++++ | ++++++

View file

@ -10,7 +10,7 @@ error[E0425]: cannot find function `sleep` in this scope
LL | sleep(); LL | sleep();
| ^^^^^ not found in this scope | ^^^^^ not found in this scope
| |
help: consider using the associated function help: consider using the method on `Self`
| |
LL | self.sleep(); LL | self.sleep();
| +++++ | +++++

View file

@ -4,7 +4,7 @@ error[E0425]: cannot find value `A_CONST` in this scope
LL | A_CONST LL | A_CONST
| ^^^^^^^ not found in this scope | ^^^^^^^ not found in this scope
| |
help: consider using the associated constant help: consider using the associated constant on `Self`
| |
LL | Self::A_CONST LL | Self::A_CONST
| ++++++ | ++++++

View file

@ -17,4 +17,12 @@ impl S {
bar(); //~ ERROR cannot find function `bar` in this scope bar(); //~ ERROR cannot find function `bar` in this scope
baz(2, 3); //~ ERROR cannot find function `baz` 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
}
} }

View file

@ -4,7 +4,7 @@ error[E0425]: cannot find function `foo` in this scope
LL | foo(); LL | foo();
| ^^^ not found in this scope | ^^^ not found in this scope
| |
help: consider using the associated function help: consider using the associated function on `Self`
| |
LL | Self::foo(); LL | Self::foo();
| ++++++ | ++++++
@ -12,13 +12,11 @@ LL | Self::foo();
error[E0425]: cannot find function `bar` in this scope error[E0425]: cannot find function `bar` in this scope
--> $DIR/assoc_fn_without_self.rs:17:9 --> $DIR/assoc_fn_without_self.rs:17:9
| |
LL | fn bar(&self) {}
| --- a method by that name is available on `Self` here
...
LL | bar(); LL | bar();
| ^^^ not found in this scope | ^^^ not found in this scope
|
help: consider using the associated function
|
LL | self.bar();
| +++++
error[E0425]: cannot find function `baz` in this scope error[E0425]: cannot find function `baz` in this scope
--> $DIR/assoc_fn_without_self.rs:18:9 --> $DIR/assoc_fn_without_self.rs:18:9
@ -26,7 +24,7 @@ error[E0425]: cannot find function `baz` in this scope
LL | baz(2, 3); LL | baz(2, 3);
| ^^^ not found in this scope | ^^^ not found in this scope
| |
help: consider using the associated function help: consider using the associated function on `Self`
| |
LL | Self::baz(2, 3); LL | Self::baz(2, 3);
| ++++++ | ++++++
@ -37,6 +35,45 @@ error[E0425]: cannot find function `foo` in this scope
LL | foo(); LL | foo();
| ^^^ not found in this scope | ^^^ not found in this scope
error: aborting due to 4 previous errors 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 method on `Self`
|
LL | self.bar();
| +++++
error[E0425]: cannot find function `baz` in this scope
--> $DIR/assoc_fn_without_self.rs:26: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:22:13
|
LL | foo();
| ^^^ not found in this scope
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0425`. For more information about this error, try `rustc --explain E0425`.