Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
53 changes: 29 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,36 @@ 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_) => Some((
sp,
"consider using the associated function",
if fn_.sig.decl.has_self() { "self." } else { "Self::" },
)),
AssocItemKind::Const(..) => Some((
sp,
"consider using the associated constant",
"Self::",
)),
_ => None
}
} else {
None
};
Expand Down Expand Up @@ -314,7 +319,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
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
}
}
43 changes: 40 additions & 3 deletions tests/ui/suggestions/assoc_fn_without_self.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,43 @@ 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
|
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
|
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
|
Expand All @@ -21,7 +58,7 @@ 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
Expand All @@ -32,11 +69,11 @@ 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`.