about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2020-09-14 15:21:38 +0100
committerDavid Wood <david@davidtw.co>2020-09-14 15:21:38 +0100
commit01f65afa4adff6dfbea84621e6851c028aaa7159 (patch)
tree53426d492d50b6db269e91bce49a8a6196b22263
parentb5f55b7e1562286798358730e06b0ba13b4c0ea6 (diff)
downloadrust-01f65afa4adff6dfbea84621e6851c028aaa7159.tar.gz
rust-01f65afa4adff6dfbea84621e6851c028aaa7159.zip
diag: improve closure/generic parameter mismatch
This commit improves the diagnostic when a type parameter is expected
and a closure is found, noting that each closure has a distinct type and
therefore could not always match the caller-chosen type of the
parameter.

Signed-off-by: David Wood <david@davidtw.co>
-rw-r--r--compiler/rustc_middle/src/ty/error.rs12
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs9
-rw-r--r--src/test/ui/issues/issue-51154.rs6
-rw-r--r--src/test/ui/issues/issue-51154.stderr15
4 files changed, 37 insertions, 5 deletions
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 7226a906e5c..fadb1d39f97 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -473,6 +473,18 @@ impl<T> Trait<T> for X {
                                  #traits-as-parameters",
                         );
                     }
+                    (ty::Param(p), ty::Closure(..) | ty::Generator(..)) => {
+                        let generics = self.generics_of(body_owner_def_id);
+                        let p_span = self.def_span(generics.type_param(p, self).def_id);
+                        if !sp.contains(p_span) {
+                            db.span_label(p_span, "this type parameter");
+                        }
+                        db.help(&format!(
+                            "every closure has a distinct type and so could not always match the \
+                             caller-chosen type of parameter `{}`",
+                            p
+                        ));
+                    }
                     (ty::Param(p), _) | (_, ty::Param(p)) => {
                         let generics = self.generics_of(body_owner_def_id);
                         let p_span = self.def_span(generics.type_param(p, self).def_id);
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index f6b768bb122..7d4bdcd9e7d 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -117,11 +117,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ty
     }
 
-    // Checks that the type of `expr` can be coerced to `expected`.
-    //
-    // N.B., this code relies on `self.diverges` to be accurate. In
-    // particular, assignments to `!` will be permitted if the
-    // diverges flag is currently "always".
+    /// Checks that the type of `expr` can be coerced to `expected`.
+    ///
+    /// N.B., this code relies on `self.diverges` to be accurate. In particular, assignments to `!`
+    /// will be permitted if the diverges flag is currently "always".
     pub fn demand_coerce_diag(
         &self,
         expr: &hir::Expr<'_>,
diff --git a/src/test/ui/issues/issue-51154.rs b/src/test/ui/issues/issue-51154.rs
new file mode 100644
index 00000000000..12903f79010
--- /dev/null
+++ b/src/test/ui/issues/issue-51154.rs
@@ -0,0 +1,6 @@
+fn foo<F: FnMut()>() {
+    let _: Box<F> = Box::new(|| ());
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-51154.stderr b/src/test/ui/issues/issue-51154.stderr
new file mode 100644
index 00000000000..3c3428f3096
--- /dev/null
+++ b/src/test/ui/issues/issue-51154.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-51154.rs:2:30
+   |
+LL | fn foo<F: FnMut()>() {
+   |        - this type parameter
+LL |     let _: Box<F> = Box::new(|| ());
+   |                              ^^^^^ expected type parameter `F`, found closure
+   |
+   = note: expected type parameter `F`
+                     found closure `[closure@$DIR/issue-51154.rs:2:30: 2:35]`
+   = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.