about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2023-09-23 01:34:50 +0000
committerEsteban Küber <esteban@kuber.com.ar>2023-09-23 01:34:50 +0000
commitc4a4926083e9f0b9aeef549f93cb66cd9d4076d7 (patch)
treef098d081df9591e755a7f8e304248be6e4aa7746
parent0fd7ce99b0508aff7f7a2c639871de4e8080e3f8 (diff)
downloadrust-c4a4926083e9f0b9aeef549f93cb66cd9d4076d7.tar.gz
rust-c4a4926083e9f0b9aeef549f93cb66cd9d4076d7.zip
More accurate suggestion for `self.` and `Self::`
Fix #115992.
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs17
-rw-r--r--tests/ui/suggestions/assoc_fn_without_self.rs8
-rw-r--r--tests/ui/suggestions/assoc_fn_without_self.stderr40
3 files changed, 57 insertions, 8 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c34b7df9b46..44dba9b7be7 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -224,14 +224,21 @@ 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
+                        if 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
+                            return match &i.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).
+                                    false
+                                }
+                                AssocItemKind::Fn(_) | AssocItemKind::Const(..) => true,
+                                _ => false
+                            }
                         }
                         false
                     })
diff --git a/tests/ui/suggestions/assoc_fn_without_self.rs b/tests/ui/suggestions/assoc_fn_without_self.rs
index 778d9847773..35c16ef3e9f 100644
--- a/tests/ui/suggestions/assoc_fn_without_self.rs
+++ b/tests/ui/suggestions/assoc_fn_without_self.rs
@@ -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
+    }
 }
diff --git a/tests/ui/suggestions/assoc_fn_without_self.stderr b/tests/ui/suggestions/assoc_fn_without_self.stderr
index febdd67338c..a7fab36bf8d 100644
--- a/tests/ui/suggestions/assoc_fn_without_self.stderr
+++ b/tests/ui/suggestions/assoc_fn_without_self.stderr
@@ -14,6 +14,40 @@ error[E0425]: cannot find function `bar` in this scope
    |
 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
    |
 help: consider using the associated function
    |
@@ -21,7 +55,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
@@ -32,11 +66,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`.