about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-11-06 03:28:17 +0100
committerGitHub <noreply@github.com>2019-11-06 03:28:17 +0100
commit32e745fc9449d6ab066079025d0b4685e0d6373b (patch)
tree37ed4c2998fbb45bbd7557486ba5f378d6bfed7d
parent409b2bf941b2724a028f65518c64f799f205a186 (diff)
parentb0f258b2c4c5bc0764890e4989874783a8d37db3 (diff)
downloadrust-32e745fc9449d6ab066079025d0b4685e0d6373b.tar.gz
rust-32e745fc9449d6ab066079025d0b4685e0d6373b.zip
Rollup merge of #66101 - estebank:break-tail-e0308, r=Centril
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.
-rw-r--r--src/librustc/traits/error_reporting.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs2
-rw-r--r--src/librustc_typeck/check/expr.rs10
-rw-r--r--src/librustc_typeck/check/mod.rs14
-rw-r--r--src/test/ui/type/type-error-break-tail.rs8
-rw-r--r--src/test/ui/type/type-error-break-tail.stderr18
6 files changed, 44 insertions, 10 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 1f7bce1c644..888d84d69fa 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -1231,7 +1231,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<ty::TraitRef<'tcx>>,
         points_at_arg: bool,
     ) {
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index b4e07e4a0df..af892bf8179 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 8668dd99a8c..81e4bb6f2ad 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 ee0fe48cc8b..fcafb0e88da 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4245,7 +4245,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>,
@@ -4272,7 +4272,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>,
@@ -4385,7 +4385,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>,
@@ -4453,7 +4453,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>,
@@ -4497,7 +4497,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,
@@ -4536,7 +4536,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>,
@@ -4602,7 +4602,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 00000000000..d4e3e93d06b
--- /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 00000000000..e5297d9a596
--- /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`.