Skip to content

Commit

Permalink
Ensure that unevaluated constants of type ! are present in the MIR
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed Dec 9, 2019
1 parent df26968 commit d2ed209
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/librustc_mir/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
_ => false,
};

unpack!(block = this.as_local_rvalue(block, source));
// (#66975) Source could be a const of type `!`, so has to
// exist in the generated MIR.
unpack!(block = this.as_temp(
block,
this.local_scope(),
source,
Mutability::Mut,
));

// This is an optimization. If the expression was a call then we already have an
// unreachable block. Don't bother to terminate it and create a new one.
Expand Down
28 changes: 28 additions & 0 deletions src/test/mir-opt/retain-never-const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Regression test for #66975 - ensure that we don't keep unevaluated
// `!`-typed constants until codegen.

// Force generation of optimized mir for functions that do not reach codegen.
// compile-flags: --emit mir,link

#![feature(const_panic)]

struct PrintName<T>(T);

impl<T> PrintName<T> {
const VOID: ! = panic!();
}

fn no_codegen<T>() {
let _ = PrintName::<T>::VOID;
}

fn main() {}

// END RUST SOURCE
// START rustc.no_codegen.PreCodegen.after.mir
// bb0: {
// StorageLive(_1);
// _1 = const PrintName::<T>::VOID;
// unreachable;
// }
// END rustc.no_codegen.PreCodegen.after.mir
18 changes: 18 additions & 0 deletions src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Regression test for #66975
#![warn(const_err)]

struct PrintName<T>(T);

impl<T> PrintName<T> {
const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
//~^ WARN any use of this value will cause an error
}

fn f<T>() {
let _ = PrintName::<T>::VOID;
//~^ ERROR erroneous constant encountered
}

pub fn main() {
f::<()>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
warning: any use of this value will cause an error
--> $DIR/index-out-of-bounds-never-type.rs:7:61
|
LL | const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
| --------------------------------------------------------^^^^^---
| |
| index out of bounds: the len is 0 but the index is 0
|
note: lint level defined here
--> $DIR/index-out-of-bounds-never-type.rs:2:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^

error: erroneous constant encountered
--> $DIR/index-out-of-bounds-never-type.rs:12:13
|
LL | let _ = PrintName::<T>::VOID;
| ^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

15 changes: 15 additions & 0 deletions src/test/ui/consts/const-eval/panic-assoc-never-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Regression test for #66975
#![warn(const_err)]
#![feature(const_panic)]

struct PrintName;

impl PrintName {
const VOID: ! = panic!();
//~^ WARN any use of this value will cause an error
}

fn main() {
let _ = PrintName::VOID;
//~^ ERROR erroneous constant used
}
24 changes: 24 additions & 0 deletions src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
warning: any use of this value will cause an error
--> $DIR/panic-assoc-never-type.rs:8:21
|
LL | const VOID: ! = panic!();
| ----------------^^^^^^^^-
| |
| the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:8:21
|
note: lint level defined here
--> $DIR/panic-assoc-never-type.rs:2:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0080]: erroneous constant used
--> $DIR/panic-assoc-never-type.rs:13:13
|
LL | let _ = PrintName::VOID;
| ^^^^^^^^^^^^^^^ referenced constant has errors

error: aborting due to previous error

For more information about this error, try `rustc --explain E0080`.
11 changes: 11 additions & 0 deletions src/test/ui/consts/const-eval/panic-never-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Regression test for #66975
#![warn(const_err)]
#![feature(const_panic)]

const VOID: ! = panic!();
//~^ WARN any use of this value will cause an error

fn main() {
let _ = VOID;
//~^ ERROR erroneous constant used
}
24 changes: 24 additions & 0 deletions src/test/ui/consts/const-eval/panic-never-type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
warning: any use of this value will cause an error
--> $DIR/panic-never-type.rs:5:17
|
LL | const VOID: ! = panic!();
| ----------------^^^^^^^^-
| |
| the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:5:17
|
note: lint level defined here
--> $DIR/panic-never-type.rs:2:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0080]: erroneous constant used
--> $DIR/panic-never-type.rs:9:13
|
LL | let _ = VOID;
| ^^^^ referenced constant has errors

error: aborting due to previous error

For more information about this error, try `rustc --explain E0080`.

0 comments on commit d2ed209

Please sign in to comment.