about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2022-02-13 13:06:06 -0700
committerMichael Howell <michael@notriddle.com>2022-02-16 09:12:32 -0700
commit65fc7058d88f28f6fa33970ef866b59e33f4255b (patch)
tree1ea83f641e34e8ee3bc994aed4496bc164a2c044
parent05d165233794c48217e2e2bb6de8ee9763ea1084 (diff)
downloadrust-65fc7058d88f28f6fa33970ef866b59e33f4255b.tar.gz
rust-65fc7058d88f28f6fa33970ef866b59e33f4255b.zip
Do not suggest "is a function" for free variables
Part of #82323
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs12
-rw-r--r--src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs22
-rw-r--r--src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr32
-rw-r--r--src/test/ui/functions-closures/fn-help-with-err.rs16
-rw-r--r--src/test/ui/functions-closures/fn-help-with-err.stderr24
5 files changed, 106 insertions, 0 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 8aa22852a6f..f2b228fa002 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -40,7 +40,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     Err(..) => return false,
                 };
 
+                // This conditional prevents us from asking to call errors and unresolved types.
+                // It might seem that we can use `predicate_must_hold_modulo_regions`,
+                // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
+                // type resolution always gives a "maybe" here.
+                if self.autoderef(span, ty).any(|(ty, _)| {
+                    info!("check deref {:?} error", ty);
+                    matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
+                }) {
+                    return false;
+                }
+
                 self.autoderef(span, ty).any(|(ty, _)| {
+                    info!("check deref {:?} impl FnOnce", ty);
                     self.probe(|_| {
                         let fn_once_substs = tcx.mk_substs_trait(
                             ty,
diff --git a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs
new file mode 100644
index 00000000000..26deb598762
--- /dev/null
+++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs
@@ -0,0 +1,22 @@
+struct Struct<T>(T);
+impl Struct<T>
+//~^ ERROR cannot find type `T` in this scope
+//~| NOTE not found in this scope
+//~| HELP you might be missing a type parameter
+where
+    T: Copy,
+    //~^ ERROR cannot find type `T` in this scope
+    //~| NOTE not found in this scope
+{
+    // The part where it claims that there is no method named `len` is a bug. Feel free to fix it.
+    // This test is intended to ensure that a different bug, where it claimed
+    // that `v` was a function, does not regress.
+    fn method(v: Vec<u8>) { v.len(); }
+    //~^ ERROR type annotations needed
+    //~| NOTE cannot infer type
+    //~| NOTE type must be known at this point
+    //~| ERROR no method named `len`
+    //~| NOTE private field, not a method
+}
+
+fn main() {}
diff --git a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr
new file mode 100644
index 00000000000..958ce3c25d0
--- /dev/null
+++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr
@@ -0,0 +1,32 @@
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/fn-help-with-err-generic-is-not-function.rs:2:13
+   |
+LL | impl Struct<T>
+   |     -       ^ not found in this scope
+   |     |
+   |     help: you might be missing a type parameter: `<T>`
+
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/fn-help-with-err-generic-is-not-function.rs:7:5
+   |
+LL |     T: Copy,
+   |     ^ not found in this scope
+
+error[E0282]: type annotations needed
+  --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31
+   |
+LL |     fn method(v: Vec<u8>) { v.len(); }
+   |                               ^^^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error[E0599]: no method named `len` found for struct `Vec<u8>` in the current scope
+  --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31
+   |
+LL |     fn method(v: Vec<u8>) { v.len(); }
+   |                               ^^^ private field, not a method
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0282, E0412, E0599.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/functions-closures/fn-help-with-err.rs b/src/test/ui/functions-closures/fn-help-with-err.rs
new file mode 100644
index 00000000000..f8a81af786f
--- /dev/null
+++ b/src/test/ui/functions-closures/fn-help-with-err.rs
@@ -0,0 +1,16 @@
+// This test case checks the behavior of typeck::check::method::suggest::is_fn on Ty::Error.
+fn main() {
+    let arc = std::sync::Arc::new(oops);
+    //~^ ERROR cannot find value `oops` in this scope
+    //~| NOTE not found
+    // The error "note: `arc` is a function, perhaps you wish to call it" MUST NOT appear.
+    arc.blablabla();
+    //~^ ERROR no method named `blablabla`
+    //~| NOTE method not found
+    let arc2 = std::sync::Arc::new(|| 1);
+    // The error "note: `arc2` is a function, perhaps you wish to call it" SHOULD appear
+    arc2.blablabla();
+    //~^ ERROR no method named `blablabla`
+    //~| NOTE method not found
+    //~| NOTE `arc2` is a function, perhaps you wish to call it
+}
diff --git a/src/test/ui/functions-closures/fn-help-with-err.stderr b/src/test/ui/functions-closures/fn-help-with-err.stderr
new file mode 100644
index 00000000000..4d6b3282ad9
--- /dev/null
+++ b/src/test/ui/functions-closures/fn-help-with-err.stderr
@@ -0,0 +1,24 @@
+error[E0425]: cannot find value `oops` in this scope
+  --> $DIR/fn-help-with-err.rs:3:35
+   |
+LL |     let arc = std::sync::Arc::new(oops);
+   |                                   ^^^^ not found in this scope
+
+error[E0599]: no method named `blablabla` found for struct `Arc<_>` in the current scope
+  --> $DIR/fn-help-with-err.rs:7:9
+   |
+LL |     arc.blablabla();
+   |         ^^^^^^^^^ method not found in `Arc<_>`
+
+error[E0599]: no method named `blablabla` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:10:36: 10:40]>` in the current scope
+  --> $DIR/fn-help-with-err.rs:12:10
+   |
+LL |     arc2.blablabla();
+   |          ^^^^^^^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:10:36: 10:40]>`
+   |
+   = note: `arc2` is a function, perhaps you wish to call it
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0425, E0599.
+For more information about an error, try `rustc --explain E0425`.