about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2022-11-11 12:12:30 -0500
committerGitHub <noreply@github.com>2022-11-11 12:12:30 -0500
commitf00897e2f4a411b0fa8ffb403a114bca007f0601 (patch)
treeadc85976544405647e3a066a3c84c3243bf2f7e7
parentfd5ff82f28be617c6116a7a16bb1a32b401e9459 (diff)
parent27164495881d2d3d1bb1ef79850b00f1e9989ba7 (diff)
downloadrust-f00897e2f4a411b0fa8ffb403a114bca007f0601.tar.gz
rust-f00897e2f4a411b0fa8ffb403a114bca007f0601.zip
Rollup merge of #103531 - chenyukang:yukang/fix-103474, r=estebank
Suggest calling the instance method of the same name when method not found

Fixes #103474
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs24
-rw-r--r--src/test/ui/resolve/issue-103474.rs28
-rw-r--r--src/test/ui/resolve/issue-103474.stderr35
-rw-r--r--src/test/ui/resolve/issue-2356.stderr4
-rw-r--r--src/test/ui/self/class-missing-self.stderr4
-rw-r--r--src/test/ui/suggestions/assoc_fn_without_self.stderr9
6 files changed, 88 insertions, 16 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 2587a9c4b34..f2bfec5a2a3 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -219,26 +219,26 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             let (mod_prefix, mod_str, suggestion) = if path.len() == 1 {
                 debug!(?self.diagnostic_metadata.current_impl_items);
                 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
-                    && self.current_trait_ref.is_none()
                     && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
+                    && let Some(items) = self.diagnostic_metadata.current_impl_items
                     && let Some(item) = items.iter().find(|i| {
-                        if let AssocItemKind::Fn(fn_) = &i.kind
-                            && !fn_.sig.decl.has_self()
-                            && i.ident.name == item_str.name
+                        if let AssocItemKind::Fn(_) = &i.kind && i.ident.name == item_str.name
                         {
                             debug!(?item_str.name);
-                            debug!(?fn_.sig.decl.inputs);
                             return true
                         }
                         false
                     })
+                    && let AssocItemKind::Fn(fn_) = &item.kind
                 {
+                    debug!(?fn_);
+                    let self_sugg = if fn_.sig.decl.has_self() { "self." } else { "Self::" };
                     Some((
-                        item_span,
+                        item_span.shrink_to_lo(),
                         "consider using the associated function",
-                        format!("Self::{}", item.ident)
+                        self_sugg.to_string()
                     ))
                 } else {
                     None
@@ -396,11 +396,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
     }
 
     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 item_str = path_last_segment.ident;
         // 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(
                 span,
                 "you might have meant to use `self` here instead",
@@ -451,7 +453,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
         let path_str = Segment::names_to_string(path);
         let ident_span = path.last().map_or(span, |ident| ident.ident.span);
-
         let mut candidates = self
             .r
             .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
@@ -1542,7 +1543,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 _ => None,
             }
         }
-
         // Fields are generally expected in the same contexts as locals.
         if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
             if let Some(node_id) =
diff --git a/src/test/ui/resolve/issue-103474.rs b/src/test/ui/resolve/issue-103474.rs
new file mode 100644
index 00000000000..14f2259e1d4
--- /dev/null
+++ b/src/test/ui/resolve/issue-103474.rs
@@ -0,0 +1,28 @@
+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
+    }
+}
+
+// https://github.com/rust-lang/rust/pull/103531#discussion_r1004728080
+struct Foo {
+    i: i32,
+}
+
+impl Foo {
+    fn needs_self() {
+        this.i
+        //~^ ERROR cannot find value `this` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-103474.stderr b/src/test/ui/resolve/issue-103474.stderr
new file mode 100644
index 00000000000..415d231552a
--- /dev/null
+++ b/src/test/ui/resolve/issue-103474.stderr
@@ -0,0 +1,35 @@
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-103474.rs:23:9
+   |
+LL |         this.i
+   |         ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         self.i
+   |         ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn needs_self(&self) {
+   |                   +++++
+
+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 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr
index e7c53ff44e6..36f3da7c955 100644
--- a/src/test/ui/resolve/issue-2356.stderr
+++ b/src/test/ui/resolve/issue-2356.stderr
@@ -85,7 +85,7 @@ LL |         static_method();
 help: consider using the associated function
    |
 LL |         Self::static_method();
-   |         ~~~~~~~~~~~~~~~~~~~
+   |         ++++++
 
 error[E0425]: cannot find function `purr` in this scope
   --> $DIR/issue-2356.rs:54:9
@@ -114,7 +114,7 @@ LL |     grow_older();
 help: consider using the associated function
    |
 LL |     Self::grow_older();
-   |     ~~~~~~~~~~~~~~~~
+   |     ++++++
 
 error[E0425]: cannot find function `shave` in this scope
   --> $DIR/issue-2356.rs:74:5
diff --git a/src/test/ui/self/class-missing-self.stderr b/src/test/ui/self/class-missing-self.stderr
index d501200d73c..063c3f013c5 100644
--- a/src/test/ui/self/class-missing-self.stderr
+++ b/src/test/ui/self/class-missing-self.stderr
@@ -10,6 +10,10 @@ error[E0425]: cannot find function `sleep` in this scope
 LL |       sleep();
    |       ^^^^^ not found in this scope
    |
+help: consider using the associated function
+   |
+LL |       self.sleep();
+   |       +++++
 help: consider importing this function
    |
 LL | use std::thread::sleep;
diff --git a/src/test/ui/suggestions/assoc_fn_without_self.stderr b/src/test/ui/suggestions/assoc_fn_without_self.stderr
index 88920b85290..febdd67338c 100644
--- a/src/test/ui/suggestions/assoc_fn_without_self.stderr
+++ b/src/test/ui/suggestions/assoc_fn_without_self.stderr
@@ -7,13 +7,18 @@ LL |         foo();
 help: consider using the associated function
    |
 LL |         Self::foo();
-   |         ~~~~~~~~~
+   |         ++++++
 
 error[E0425]: cannot find function `bar` in this scope
   --> $DIR/assoc_fn_without_self.rs:17:9
    |
 LL |         bar();
    |         ^^^ not found in this scope
+   |
+help: consider using the associated function
+   |
+LL |         self.bar();
+   |         +++++
 
 error[E0425]: cannot find function `baz` in this scope
   --> $DIR/assoc_fn_without_self.rs:18:9
@@ -24,7 +29,7 @@ LL |         baz(2, 3);
 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