]> git.lizzy.rs Git - rust.git/commitdiff
Fix behaviour of divergence in while loop conditions
authorvarkor <github@varkor.com>
Thu, 24 May 2018 22:27:36 +0000 (23:27 +0100)
committervarkor <github@varkor.com>
Fri, 25 May 2018 15:53:32 +0000 (16:53 +0100)
This fixes `'a: while break 'a {};` being treated as diverging, by tracking break expressions in the same way as in `loop` expressions.

src/librustc_typeck/check/mod.rs
src/test/ui/break-while-condition.rs [new file with mode: 0644]
src/test/ui/break-while-condition.stderr [new file with mode: 0644]

index 70d299437a6e9401dc0b4f826e1de441c9c56cb1..b0766f059130119eb95eaa422a78455cc7fda050 100644 (file)
@@ -3841,10 +3841,10 @@ fn check_expr_kind(&self,
               let ctxt = BreakableCtxt {
                   // cannot use break with a value from a while loop
                   coerce: None,
-                  may_break: true,
+                  may_break: false,  // Will get updated if/when we find a `break`.
               };
 
-              self.with_breakable_ctxt(expr.id, ctxt, || {
+              let (ctxt, ()) = self.with_breakable_ctxt(expr.id, ctxt, || {
                   self.check_expr_has_type_or_error(&cond, tcx.types.bool);
                   let cond_diverging = self.diverges.get();
                   self.check_block_no_value(&body);
@@ -3853,6 +3853,12 @@ fn check_expr_kind(&self,
                   self.diverges.set(cond_diverging);
               });
 
+              if ctxt.may_break {
+                  // No way to know whether it's diverging because
+                  // of a `break` or an outer `break` or `return`.
+                  self.diverges.set(Diverges::Maybe);
+              }
+
               self.tcx.mk_nil()
           }
           hir::ExprLoop(ref body, _, source) => {
@@ -3871,7 +3877,7 @@ fn check_expr_kind(&self,
 
               let ctxt = BreakableCtxt {
                   coerce,
-                  may_break: false, // will get updated if/when we find a `break`
+                  may_break: false, // Will get updated if/when we find a `break`.
               };
 
               let (ctxt, ()) = self.with_breakable_ctxt(expr.id, ctxt, || {
@@ -3880,7 +3886,7 @@ fn check_expr_kind(&self,
 
               if ctxt.may_break {
                   // No way to know whether it's diverging because
-                  // of a `break` or an outer `break` or `return.
+                  // of a `break` or an outer `break` or `return`.
                   self.diverges.set(Diverges::Maybe);
               }
 
diff --git a/src/test/ui/break-while-condition.rs b/src/test/ui/break-while-condition.rs
new file mode 100644 (file)
index 0000000..cc5d17e
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(never_type)]
+
+fn main() {
+    let _: ! = { //~ ERROR mismatched types
+        'a: while break 'a {};
+    };
+}
diff --git a/src/test/ui/break-while-condition.stderr b/src/test/ui/break-while-condition.stderr
new file mode 100644 (file)
index 0000000..5abf60c
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/break-while-condition.rs:14:16
+   |
+LL |       let _: ! = { //~ ERROR mismatched types
+   |  ________________^
+LL | |         'a: while break 'a {};
+LL | |     };
+   | |_____^ expected !, found ()
+   |
+   = note: expected type `!`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.