diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 263b052e71f..cff2b41e9ec 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -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 _>`".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::>().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 {}>`", + args, + fn_sig.output().skip_binder().to_string(), + )) + } _ => (String::new(), "a type".to_owned()), }; let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))]; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 129ea9b5b67..02593d4d609 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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) } } diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs index 9c1e609ce64..8f48483c254 100644 --- a/src/test/ui/inference/cannot-infer-closure.rs +++ b/src/test/ui/inference/cannot-infer-closure.rs @@ -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) }; } diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr index b8ca099aec1..20b2784a45d 100644 --- a/src/test/ui/inference/cannot-infer-closure.stderr +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -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 _>` -LL | Err(())?; - | ^^^^^^^^ cannot infer type +LL | let x = |a: (), b: ()| { + | - consider giving `x` a boxed closure type like `Box std::result::Result<(), _>>` +LL | Err(a)?; + | ^^^^^^^ cannot infer type error: aborting due to previous error