From b0f258b2c4c5bc0764890e4989874783a8d37db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 4 Nov 2019 18:47:02 -0800 Subject: [PATCH] Tweak type mismatch caused by break on tail expr When `break;` has a type mismatch because the `Destination` points at a tail expression with an obligation flowing from a return type, point at the return type. Fix #39968. --- src/librustc/traits/error_reporting.rs | 2 +- src/librustc_typeck/check/demand.rs | 2 +- src/librustc_typeck/check/expr.rs | 10 +++++++++- src/librustc_typeck/check/mod.rs | 14 +++++++------- src/test/ui/type/type-error-break-tail.rs | 8 ++++++++ src/test/ui/type/type-error-break-tail.stderr | 18 ++++++++++++++++++ 6 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/type/type-error-break-tail.rs create mode 100644 src/test/ui/type/type-error-break-tail.stderr diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b55c0f29a70ec..d32a4eee5ae8b 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1169,7 +1169,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn suggest_fn_call( &self, obligation: &PredicateObligation<'tcx>, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, trait_ref: &ty::Binder>, points_at_arg: bool, ) { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index b4e07e4a0dfb4..af892bf8179f2 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -553,7 +553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_for_cast( &self, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 8668dd99a8cf4..81e4bb6f2ad8b 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -583,7 +583,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { assert!(e_ty.is_unit()); let ty = coerce.expected_ty(); - coerce.coerce_forced_unit(self, &cause, &mut |err| { + coerce.coerce_forced_unit(self, &cause, &mut |mut err| { + self.suggest_mismatched_types_on_tail( + &mut err, + expr, + ty, + e_ty, + cause.span, + target_id, + ); let val = match ty.kind { ty::Bool => "true", ty::Char => "'a'", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f7132cd868aac..8ecf736df410d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4246,7 +4246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// - Possible missing return type if the return type is the default, and not `fn main()`. pub fn suggest_mismatched_types_on_tail( &self, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, expr: &'tcx hir::Expr, expected: Ty<'tcx>, found: Ty<'tcx>, @@ -4273,7 +4273,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// ``` fn suggest_fn_call( &self, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr, expected: Ty<'tcx>, found: Ty<'tcx>, @@ -4386,7 +4386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn suggest_ref_or_into( &self, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr, expected: Ty<'tcx>, found: Ty<'tcx>, @@ -4454,7 +4454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// in the heap by calling `Box::new()`. fn suggest_boxing_when_appropriate( &self, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr, expected: Ty<'tcx>, found: Ty<'tcx>, @@ -4498,7 +4498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// it suggests adding a semicolon. fn suggest_missing_semicolon( &self, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, expression: &'tcx hir::Expr, expected: Ty<'tcx>, cause_span: Span, @@ -4537,7 +4537,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// type. fn suggest_missing_return_type( &self, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, fn_decl: &hir::FnDecl, expected: Ty<'tcx>, found: Ty<'tcx>, @@ -4603,7 +4603,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// `.await` to the tail of the expression. fn suggest_missing_await( &self, - err: &mut DiagnosticBuilder<'tcx>, + err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr, expected: Ty<'tcx>, found: Ty<'tcx>, diff --git a/src/test/ui/type/type-error-break-tail.rs b/src/test/ui/type/type-error-break-tail.rs new file mode 100644 index 0000000000000..d4e3e93d06bc7 --- /dev/null +++ b/src/test/ui/type/type-error-break-tail.rs @@ -0,0 +1,8 @@ +fn loop_ending() -> i32 { + loop { + if false { break; } //~ ERROR mismatched types + return 42; + } +} + +fn main() {} diff --git a/src/test/ui/type/type-error-break-tail.stderr b/src/test/ui/type/type-error-break-tail.stderr new file mode 100644 index 0000000000000..e5297d9a596d8 --- /dev/null +++ b/src/test/ui/type/type-error-break-tail.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/type-error-break-tail.rs:3:20 + | +LL | fn loop_ending() -> i32 { + | --- expected `i32` because of return type +LL | loop { +LL | if false { break; } + | ^^^^^ + | | + | expected i32, found () + | help: give it a value of the expected type: `break 42` + | + = note: expected type `i32` + found type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.