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.
This commit is contained in:
Esteban Küber 2019-08-12 16:50:46 -07:00
parent 60960a260f
commit b8708e2c9a
7 changed files with 97 additions and 2 deletions

View File

@ -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<Fn() -> _>`".to_string(),
),
_ => (String::new(), "a type".to_owned()),
};
let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];

View File

@ -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(())
};
}

View File

@ -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`.

View File

@ -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(())
};
}

View File

@ -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`.

View File

@ -0,0 +1,6 @@
fn main() {
let x = || {
Err(())?; //~ ERROR type annotations needed for the closure
Ok(())
};
}

View File

@ -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<Fn() -> _>`
LL | Err(())?;
| ^^^^^^^^ cannot infer type
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.