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:
commit
61b38b216a
9 changed files with 128 additions and 37 deletions
|
@ -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,
|
||||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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()
|
||||||
| +++++
|
| +++++
|
||||||
|
|
|
@ -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();
|
||||||
| ++++++
|
| ++++++
|
||||||
|
|
|
@ -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();
|
||||||
| +++++
|
| +++++
|
||||||
|
|
|
@ -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
|
||||||
| ++++++
|
| ++++++
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue