1
Fork 0

suggest calling the method of the same name when method not found

This commit is contained in:
yukang 2022-10-26 00:15:47 +08:00
parent 9be2f35a4c
commit 32a2f0dddb
6 changed files with 61 additions and 16 deletions

View file

@ -213,26 +213,26 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let (mod_prefix, mod_str, suggestion) = if path.len() == 1 { let (mod_prefix, mod_str, suggestion) = if path.len() == 1 {
debug!(?self.diagnostic_metadata.current_impl_items); debug!(?self.diagnostic_metadata.current_impl_items);
debug!(?self.diagnostic_metadata.current_function); debug!(?self.diagnostic_metadata.current_function);
let suggestion = if let Some(items) = self.diagnostic_metadata.current_impl_items let suggestion = if self.current_trait_ref.is_none()
&& let Some((fn_kind, _)) = self.diagnostic_metadata.current_function && let Some((fn_kind, _)) = self.diagnostic_metadata.current_function
&& self.current_trait_ref.is_none()
&& let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt() && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
&& 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(fn_) = &i.kind if let AssocItemKind::Fn(_) = &i.kind && i.ident.name == item_str.name
&& !fn_.sig.decl.has_self()
&& i.ident.name == item_str.name
{ {
debug!(?item_str.name); debug!(?item_str.name);
debug!(?fn_.sig.decl.inputs);
return true return true
} }
false false
}) })
&& let AssocItemKind::Fn(fn_) = &item.kind
{ {
debug!(?fn_);
let self_sugg = if fn_.sig.decl.has_self() { "self." } else { "Self::" };
Some(( Some((
item_span, item_span.shrink_to_lo(),
"consider using the associated function", "consider using the associated function",
format!("Self::{}", item.ident) self_sugg.to_string()
)) ))
} else { } else {
None None
@ -381,11 +381,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
} }
fn suggest_self_or_self_ref(&mut self, err: &mut Diagnostic, path: &[Segment], span: Span) { fn suggest_self_or_self_ref(&mut self, err: &mut Diagnostic, path: &[Segment], span: Span) {
let is_assoc_fn = self.self_type_is_available(); if !self.self_type_is_available() {
return;
}
let Some(path_last_segment) = path.last() else { return }; let Some(path_last_segment) = path.last() else { return };
let item_str = path_last_segment.ident; let item_str = path_last_segment.ident;
// Emit help message for fake-self from other languages (e.g., `this` in Javascript). // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
if ["this", "my"].contains(&item_str.as_str()) && is_assoc_fn { if ["this", "my"].contains(&item_str.as_str()) {
err.span_suggestion_short( err.span_suggestion_short(
span, span,
"you might have meant to use `self` here instead", "you might have meant to use `self` here instead",
@ -436,7 +438,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _)); let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
let path_str = Segment::names_to_string(path); let path_str = Segment::names_to_string(path);
let ident_span = path.last().map_or(span, |ident| ident.ident.span); let ident_span = path.last().map_or(span, |ident| ident.ident.span);
let mut candidates = self let mut candidates = self
.r .r
.lookup_import_candidates(ident, ns, &self.parent_scope, is_expected) .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
@ -1512,7 +1513,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
_ => None, _ => None,
} }
} }
// Fields are generally expected in the same contexts as locals. // Fields are generally expected in the same contexts as locals.
if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) { if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
if let Some(node_id) = if let Some(node_id) =

View file

@ -0,0 +1,16 @@
struct S {}
impl S {
fn first(&self) {}
fn second(&self) {
first()
//~^ ERROR cannot find function `first` in this scope
}
fn third(&self) {
no_method_err()
//~^ ERROR cannot find function `no_method_err` in this scope
}
}
fn main() {}

View file

@ -0,0 +1,20 @@
error[E0425]: cannot find function `first` in this scope
--> $DIR/issue-103474.rs:6:9
|
LL | first()
| ^^^^^ not found in this scope
|
help: consider using the associated function
|
LL | self.first()
| +++++
error[E0425]: cannot find function `no_method_err` in this scope
--> $DIR/issue-103474.rs:11:9
|
LL | no_method_err()
| ^^^^^^^^^^^^^ not found in this scope
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0425`.

View file

@ -85,7 +85,7 @@ LL | static_method();
help: consider using the associated function help: consider using the associated function
| |
LL | Self::static_method(); LL | Self::static_method();
| ~~~~~~~~~~~~~~~~~~~ | ++++++
error[E0425]: cannot find function `purr` in this scope error[E0425]: cannot find function `purr` in this scope
--> $DIR/issue-2356.rs:54:9 --> $DIR/issue-2356.rs:54:9
@ -114,7 +114,7 @@ LL | grow_older();
help: consider using the associated function help: consider using the associated function
| |
LL | Self::grow_older(); LL | Self::grow_older();
| ~~~~~~~~~~~~~~~~ | ++++++
error[E0425]: cannot find function `shave` in this scope error[E0425]: cannot find function `shave` in this scope
--> $DIR/issue-2356.rs:74:5 --> $DIR/issue-2356.rs:74:5

View file

@ -10,6 +10,10 @@ 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
|
LL | self.sleep();
| +++++
help: consider importing this function help: consider importing this function
| |
LL | use std::thread::sleep; LL | use std::thread::sleep;

View file

@ -7,13 +7,18 @@ LL | foo();
help: consider using the associated function help: consider using the associated function
| |
LL | Self::foo(); 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 | 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
@ -24,7 +29,7 @@ LL | baz(2, 3);
help: consider using the associated function help: consider using the associated function
| |
LL | Self::baz(2, 3); LL | Self::baz(2, 3);
| ~~~~~~~~~ | ++++++
error[E0425]: cannot find function `foo` in this scope error[E0425]: cannot find function `foo` in this scope
--> $DIR/assoc_fn_without_self.rs:14:13 --> $DIR/assoc_fn_without_self.rs:14:13