Resolve types when suggesting boxed closure

This commit is contained in:
Esteban Küber 2019-08-12 18:12:19 -07:00
parent b8708e2c9a
commit 3b6d46c640
4 changed files with 30 additions and 11 deletions

View file

@ -175,10 +175,26 @@ 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(),
),
Some(ty::TyS { sty: ty::TyKind::Closure(def_id, substs), .. }) => {
let msg = " for the closure".to_string();
let fn_sig = substs.closure_sig(*def_id, self.tcx);
let args = fn_sig.inputs()
.skip_binder()
.iter()
.next()
.map(|args| args.tuple_fields()
.map(|arg| arg.to_string())
.collect::<Vec<_>>().join(", "))
.unwrap_or_else(String::new);
// This suggestion is incomplete, as the user will get further type inference
// errors due to the `_` placeholders and the introduction of `Box`, but it does
// nudge them in the right direction.
(msg, format!(
"a boxed closure type like `Box<Fn({}) -> {}>`",
args,
fn_sig.output().skip_binder().to_string(),
))
}
_ => (String::new(), "a type".to_owned()),
};
let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];

View file

@ -2068,6 +2068,9 @@ impl<'tcx> TyS<'tcx> {
Error => { // ignore errors (#54954)
ty::Binder::dummy(FnSig::fake())
}
Closure(..) => bug!(
"to get the signature of a closure, use `closure_sig()` not `fn_sig()`",
),
_ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
}
}

View file

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

View file

@ -1,10 +1,10 @@
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
LL | let x = |a: (), b: ()| {
| - consider giving `x` a boxed closure type like `Box<Fn((), ()) -> std::result::Result<(), _>>`
LL | Err(a)?;
| ^^^^^^^ cannot infer type
error: aborting due to previous error