From 36a5244da311b9cd9a4ee04a75f15e23cf9fe891 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 22 Oct 2020 09:47:23 -0400 Subject: [PATCH] Explain where the closure return type was inferred Fixes #78193 --- compiler/rustc_typeck/src/check/coercion.rs | 22 +++++++++++++++++++ .../closures/closure-return-type-mismatch.rs | 17 ++++++++++++++ .../closure-return-type-mismatch.stderr | 21 ++++++++++++++++++ .../type-mismatch-signature-deduction.stderr | 5 +++++ 4 files changed, 65 insertions(+) create mode 100644 src/test/ui/closures/closure-return-type-mismatch.rs create mode 100644 src/test/ui/closures/closure-return-type-mismatch.stderr diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index c1485e3baf677..6da3ecde329cf 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1475,6 +1475,28 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) { self.add_impl_trait_explanation(&mut err, cause, fcx, expected, *sp, fn_output); } + + if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { + // If the closure has an explicit return type annotation, + // then a type error may occur at the first return expression we + // see in the closure (if it conflicts with the declared + // return type). Skip adding a note in this case, since it + // would be incorrect. + if !err.span.primary_spans().iter().any(|span| span == sp) { + let hir = fcx.tcx.hir(); + let body_owner = hir.body_owned_by(hir.enclosing_body_owner(fcx.body_id)); + if fcx.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) { + err.span_note( + *sp, + &format!( + "return type inferred to be `{}` here", + fcx.resolve_vars_if_possible(&expected) + ), + ); + } + } + } + err } diff --git a/src/test/ui/closures/closure-return-type-mismatch.rs b/src/test/ui/closures/closure-return-type-mismatch.rs new file mode 100644 index 0000000000000..1631bb303e54e --- /dev/null +++ b/src/test/ui/closures/closure-return-type-mismatch.rs @@ -0,0 +1,17 @@ +fn main() { + || { + if false { + return "test"; + } + let a = true; + a //~ ERROR mismatched types + }; + + || -> bool { + if false { + return "hello" //~ ERROR mismatched types + }; + let b = true; + b + }; +} diff --git a/src/test/ui/closures/closure-return-type-mismatch.stderr b/src/test/ui/closures/closure-return-type-mismatch.stderr new file mode 100644 index 0000000000000..3a89d30a05d20 --- /dev/null +++ b/src/test/ui/closures/closure-return-type-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:7:9 + | +LL | a + | ^ expected `&str`, found `bool` + | +note: return type inferred to be `&str` here + --> $DIR/closure-return-type-mismatch.rs:4:20 + | +LL | return "test"; + | ^^^^^^ + +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:12:20 + | +LL | return "hello" + | ^^^^^^^ expected `bool`, found `&str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 9e111d68a55b7..4abc0542c5142 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -6,6 +6,11 @@ LL | 5 | = note: expected type `std::result::Result<{integer}, _>` found type `{integer}` +note: return type inferred to be `std::result::Result<{integer}, _>` here + --> $DIR/type-mismatch-signature-deduction.rs:8:20 + | +LL | return Ok(6); + | ^^^^^ error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6] as Generator>::Return == i32` --> $DIR/type-mismatch-signature-deduction.rs:5:13