From b8708e2c9a264f1db74700c7471b8038e2d7f8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Aug 2019 16:50:46 -0700 Subject: [PATCH] When needing type annotations in local bindings, account for impl Trait and closures Do not suggest nonsensical types when the type inference is failing on `impl Trait` or anonymous closures. --- .../infer/error_reporting/need_type_info.rs | 18 ++++++++++++++++-- ...infer-async-enabled-impl-trait-bindings.rs | 18 ++++++++++++++++++ ...r-async-enabled-impl-trait-bindings.stderr | 19 +++++++++++++++++++ src/test/ui/inference/cannot-infer-async.rs | 16 ++++++++++++++++ .../ui/inference/cannot-infer-async.stderr | 11 +++++++++++ src/test/ui/inference/cannot-infer-closure.rs | 6 ++++++ .../ui/inference/cannot-infer-closure.stderr | 11 +++++++++++ 7 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs create mode 100644 src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr create mode 100644 src/test/ui/inference/cannot-infer-async.rs create mode 100644 src/test/ui/inference/cannot-infer-async.stderr create mode 100644 src/test/ui/inference/cannot-infer-closure.rs create mode 100644 src/test/ui/inference/cannot-infer-closure.stderr diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 770d5155777..263b052e71f 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -151,12 +151,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | the type parameter `E` is specified // ``` let (ty_msg, suffix) = match &local_visitor.found_ty { - Some(ty) if &ty.to_string() != "_" && name == "_" => { + Some(ty) if &ty.to_string() != "_" && + name == "_" && + // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. + (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings) && + !ty.is_closure() => // The suggestion doesn't make sense for closures. + { let ty = ty_to_string(ty); (format!(" for `{}`", ty), format!("the explicit type `{}`, with the type parameters specified", ty)) } - Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => { + Some(ty) if &ty.to_string() != "_" && + ty.to_string() != name && + // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. + (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings) && + !ty.is_closure() => // The suggestion doesn't make sense for closures. + { let ty = ty_to_string(ty); (format!(" for `{}`", ty), format!( @@ -165,6 +175,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { name, )) } + Some(ty) if ty.is_closure() => ( + " for the closure".to_string(), + "a boxed closure type like `Box _>`".to_string(), + ), _ => (String::new(), "a type".to_owned()), }; let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))]; diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs new file mode 100644 index 00000000000..fb6fd60c22f --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs @@ -0,0 +1,18 @@ +// edition:2018 +#![feature(async_await)] +#![feature(impl_trait_in_bindings)] +//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + +use std::io::Error; + +fn make_unit() -> Result<(), Error> { + Ok(()) +} + +fn main() { + let fut = async { + make_unit()?; //~ ERROR type annotations needed + + Ok(()) + }; +} diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr new file mode 100644 index 00000000000..67a834a2e95 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -0,0 +1,19 @@ +warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:3:12 + | +LL | #![feature(impl_trait_in_bindings)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0282]: type annotations needed for `impl std::future::Future` + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:14:9 + | +LL | let fut = async { + | --- consider giving `fut` the explicit type `impl std::future::Future`, with the type parameters specified +LL | make_unit()?; + | ^^^^^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs new file mode 100644 index 00000000000..354942121b0 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async.rs @@ -0,0 +1,16 @@ +// edition:2018 +#![feature(async_await)] + +use std::io::Error; + +fn make_unit() -> Result<(), Error> { + Ok(()) +} + +fn main() { + let fut = async { + make_unit()?; //~ ERROR type annotations needed + + Ok(()) + }; +} diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr new file mode 100644 index 00000000000..36608a11bb7 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/cannot-infer-async.rs:12:9 + | +LL | let fut = async { + | --- consider giving `fut` a type +LL | make_unit()?; + | ^^^^^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs new file mode 100644 index 00000000000..9c1e609ce64 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-closure.rs @@ -0,0 +1,6 @@ +fn main() { + let x = || { + Err(())?; //~ ERROR type annotations needed for the closure + Ok(()) + }; +} diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr new file mode 100644 index 00000000000..b8ca099aec1 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for the closure + --> $DIR/cannot-infer-closure.rs:3:9 + | +LL | let x = || { + | - consider giving `x` a boxed closure type like `Box _>` +LL | Err(())?; + | ^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`.