about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-08-12 18:12:19 -0700
committerEsteban Küber <esteban@kuber.com.ar>2019-08-12 18:12:19 -0700
commit3b6d46c6404cbb076ac07c568c6c4eb6d370994e (patch)
tree7d7b2f7b2e7677bb13cc19a70df6c32141a30e6c
parentb8708e2c9a264f1db74700c7471b8038e2d7f8da (diff)
downloadrust-3b6d46c6404cbb076ac07c568c6c4eb6d370994e.tar.gz
rust-3b6d46c6404cbb076ac07c568c6c4eb6d370994e.zip
Resolve types when suggesting boxed closure
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs24
-rw-r--r--src/librustc/ty/sty.rs3
-rw-r--r--src/test/ui/inference/cannot-infer-closure.rs6
-rw-r--r--src/test/ui/inference/cannot-infer-closure.stderr8
4 files changed, 30 insertions, 11 deletions
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<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))];
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<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