From 65fc7058d88f28f6fa33970ef866b59e33f4255b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 13 Feb 2022 13:06:06 -0700 Subject: [PATCH] Do not suggest "is a function" for free variables Part of #82323 --- .../rustc_typeck/src/check/method/suggest.rs | 12 +++++++ ...n-help-with-err-generic-is-not-function.rs | 22 +++++++++++++ ...lp-with-err-generic-is-not-function.stderr | 32 +++++++++++++++++++ .../ui/functions-closures/fn-help-with-err.rs | 16 ++++++++++ .../fn-help-with-err.stderr | 24 ++++++++++++++ 5 files changed, 106 insertions(+) create mode 100644 src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs create mode 100644 src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr create mode 100644 src/test/ui/functions-closures/fn-help-with-err.rs create mode 100644 src/test/ui/functions-closures/fn-help-with-err.stderr diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 8aa22852a6ffd..f2b228fa00268 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 0000000000000..26deb59876268 --- /dev/null +++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs @@ -0,0 +1,22 @@ +struct Struct(T); +impl Struct +//~^ 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) { 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 0000000000000..958ce3c25d027 --- /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 + | - ^ not found in this scope + | | + | help: you might be missing a type parameter: `` + +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) { v.len(); } + | ^^^ cannot infer type + | + = note: type must be known at this point + +error[E0599]: no method named `len` found for struct `Vec` in the current scope + --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31 + | +LL | fn method(v: Vec) { 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 0000000000000..f8a81af786f7e --- /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 0000000000000..4d6b3282ad9e9 --- /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`.