From 01f65afa4adff6dfbea84621e6851c028aaa7159 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 14 Sep 2020 15:21:38 +0100 Subject: [PATCH] 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 --- compiler/rustc_middle/src/ty/error.rs | 12 ++++++++++++ compiler/rustc_typeck/src/check/demand.rs | 9 ++++----- src/test/ui/issues/issue-51154.rs | 6 ++++++ src/test/ui/issues/issue-51154.stderr | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-51154.rs create mode 100644 src/test/ui/issues/issue-51154.stderr 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 Trait 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() { + let _: Box = 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() { + | - this type parameter +LL | let _: Box = 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`.