From 5724dad82ed34f4461f58b3c035b1b06747d8669 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 26 May 2018 02:48:08 +0200 Subject: [PATCH] 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 --- src/librustc_typeck/check/mod.rs | 7 +++++-- src/test/compile-fail/issue-43162.rs | 1 + src/test/ui/issue-50576.rs | 16 ++++++++++++++++ src/test/ui/issue-50576.stderr | 22 ++++++++++++++++++++++ src/test/ui/issue-50581.rs | 13 +++++++++++++ src/test/ui/issue-50581.stderr | 9 +++++++++ 6 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/issue-50576.rs create mode 100644 src/test/ui/issue-50576.stderr create mode 100644 src/test/ui/issue-50581.rs create mode 100644 src/test/ui/issue-50581.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 70d299437a6e9..16695dcef8f71 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 8f4661299e9d0..b236283f75764 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 0000000000000..b2032fb226bd1 --- /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 or the MIT license +// , 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 0000000000000..e661be2133900 --- /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 0000000000000..97b3f81eaf5fb --- /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 or the MIT license +// , 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 0000000000000..38a87b1e78a1b --- /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`.