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:
parent
60960a260f
commit
b8708e2c9a
7 changed files with 97 additions and 2 deletions
|
@ -151,12 +151,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
// | the type parameter `E` is specified
|
// | the type parameter `E` is specified
|
||||||
// ```
|
// ```
|
||||||
let (ty_msg, suffix) = match &local_visitor.found_ty {
|
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);
|
let ty = ty_to_string(ty);
|
||||||
(format!(" for `{}`", ty),
|
(format!(" for `{}`", ty),
|
||||||
format!("the explicit type `{}`, with the type parameters specified", 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);
|
let ty = ty_to_string(ty);
|
||||||
(format!(" for `{}`", ty),
|
(format!(" for `{}`", ty),
|
||||||
format!(
|
format!(
|
||||||
|
@ -165,6 +175,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
name,
|
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()),
|
_ => (String::new(), "a type".to_owned()),
|
||||||
};
|
};
|
||||||
let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
|
let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
|
||||||
|
|
|
@ -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(())
|
||||||
|
};
|
||||||
|
}
|
|
@ -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`.
|
16
src/test/ui/inference/cannot-infer-async.rs
Normal file
16
src/test/ui/inference/cannot-infer-async.rs
Normal 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(())
|
||||||
|
};
|
||||||
|
}
|
11
src/test/ui/inference/cannot-infer-async.stderr
Normal file
11
src/test/ui/inference/cannot-infer-async.stderr
Normal 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`.
|
6
src/test/ui/inference/cannot-infer-closure.rs
Normal file
6
src/test/ui/inference/cannot-infer-closure.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
fn main() {
|
||||||
|
let x = || {
|
||||||
|
Err(())?; //~ ERROR type annotations needed for the closure
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
}
|
11
src/test/ui/inference/cannot-infer-closure.stderr
Normal file
11
src/test/ui/inference/cannot-infer-closure.stderr
Normal 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`.
|
Loading…
Add table
Add a link
Reference in a new issue