about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2018-05-26 19:32:32 +0800
committerGitHub <noreply@github.com>2018-05-26 19:32:32 +0800
commit5089ebc5682ed71ee01b309c6681cb1ca127c62e (patch)
tree4a9a178d777ec0a6cc5b9a9f4de2ce6ed49eb2d9
parent239e3d2dd7e2b8a8d46eedff73018c5e17a4f051 (diff)
parent5724dad82ed34f4461f58b3c035b1b06747d8669 (diff)
downloadrust-5089ebc5682ed71ee01b309c6681cb1ca127c62e.tar.gz
rust-5089ebc5682ed71ee01b309c6681cb1ca127c62e.zip
Rollup merge of #51070 - est31:fix_break_const_ice, r=estebank
Fail typecheck if we encounter a bogus break

Lone breaks outside of loops create errors in the
loop check pass but as they are not fatal,
compilation continues.

MIR building code assumes all HIR break statements
to point to valid locations and fires ICEs if this
assumption is violated. In normal compilation,
this causes no issues, as code apparently prevents
MIR from being built if errors are present.

However, before that, typecheck runs and with it
MIR const eval. Here we operate differently
from normal compilation: it doesn't check for any
errors except for type checker ones and then
directly builds the MIR.

This constellation causes an ICE-on-error if
bogus break statements are being put into array
length expressions.

This commit fixes this ICE by letting typecheck
fail if bogus break statements are encountered.
This way, MIR const eval fails cleanly with a
type check error.

Fixes #50576
Fixes #50581
-rw-r--r--src/librustc_typeck/check/mod.rs7
-rw-r--r--src/test/compile-fail/issue-43162.rs1
-rw-r--r--src/test/ui/issue-50576.rs16
-rw-r--r--src/test/ui/issue-50576.stderr22
-rw-r--r--src/test/ui/issue-50581.rs13
-rw-r--r--src/test/ui/issue-50581.stderr9
6 files changed, 66 insertions, 2 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 70d299437a6..16695dcef8f 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3764,6 +3764,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                   }
 
                   ctxt.may_break = true;
+
+                  // the type of a `break` is always `!`, since it diverges
+                  tcx.types.never
               } else {
                   // Otherwise, we failed to find the enclosing loop;
                   // this can only happen if the `break` was not
@@ -3784,10 +3787,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                           }
                       }
                   }
+                  // There was an error, make typecheck fail
+                  tcx.types.err
               }
 
-              // the type of a `break` is always `!`, since it diverges
-              tcx.types.never
           }
           hir::ExprAgain(_) => { tcx.types.never }
           hir::ExprRet(ref expr_opt) => {
diff --git a/src/test/compile-fail/issue-43162.rs b/src/test/compile-fail/issue-43162.rs
index 8f4661299e9..b236283f757 100644
--- a/src/test/compile-fail/issue-43162.rs
+++ b/src/test/compile-fail/issue-43162.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 fn foo() -> bool {
+    //~^ ERROR E0308
     break true; //~ ERROR E0268
 }
 
diff --git a/src/test/ui/issue-50576.rs b/src/test/ui/issue-50576.rs
new file mode 100644
index 00000000000..b2032fb226b
--- /dev/null
+++ b/src/test/ui/issue-50576.rs
@@ -0,0 +1,16 @@
+// 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.
+
+fn main() {
+    |bool: [u8; break 'L]| 0;
+    //~^ ERROR [E0426]
+    //~| ERROR [E0268]
+    Vec::<[u8; break]>::new(); //~ ERROR [E0268]
+}
diff --git a/src/test/ui/issue-50576.stderr b/src/test/ui/issue-50576.stderr
new file mode 100644
index 00000000000..e661be21339
--- /dev/null
+++ b/src/test/ui/issue-50576.stderr
@@ -0,0 +1,22 @@
+error[E0426]: use of undeclared label `'L`
+  --> $DIR/issue-50576.rs:12:23
+   |
+LL |     |bool: [u8; break 'L]| 0;
+   |                       ^^ undeclared label `'L`
+
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-50576.rs:12:17
+   |
+LL |     |bool: [u8; break 'L]| 0;
+   |                 ^^^^^^^^ cannot break outside of a loop
+
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-50576.rs:15:16
+   |
+LL |     Vec::<[u8; break]>::new(); //~ ERROR [E0268]
+   |                ^^^^^ cannot break outside of a loop
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0268, E0426.
+For more information about an error, try `rustc --explain E0268`.
diff --git a/src/test/ui/issue-50581.rs b/src/test/ui/issue-50581.rs
new file mode 100644
index 00000000000..97b3f81eaf5
--- /dev/null
+++ b/src/test/ui/issue-50581.rs
@@ -0,0 +1,13 @@
+// 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.
+
+fn main() {
+    |_: [u8; break]| (); //~ ERROR [E0268]
+}
diff --git a/src/test/ui/issue-50581.stderr b/src/test/ui/issue-50581.stderr
new file mode 100644
index 00000000000..38a87b1e78a
--- /dev/null
+++ b/src/test/ui/issue-50581.stderr
@@ -0,0 +1,9 @@
+error[E0268]: `break` outside of loop
+  --> $DIR/issue-50581.rs:12:14
+   |
+LL |     |_: [u8; break]| (); //~ ERROR [E0268]
+   |              ^^^^^ cannot break outside of a loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0268`.