diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index f5dc09ccebc1e..07a44b190b20a 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -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. diff --git a/src/test/mir-opt/retain-never-const.rs b/src/test/mir-opt/retain-never-const.rs new file mode 100644 index 0000000000000..5d59b2f48429d --- /dev/null +++ b/src/test/mir-opt/retain-never-const.rs @@ -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); + +impl PrintName { + const VOID: ! = panic!(); +} + +fn no_codegen() { + let _ = PrintName::::VOID; +} + +fn main() {} + +// END RUST SOURCE +// START rustc.no_codegen.PreCodegen.after.mir +// bb0: { +// StorageLive(_1); +// _1 = const PrintName::::VOID; +// unreachable; +// } +// END rustc.no_codegen.PreCodegen.after.mir diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs new file mode 100644 index 0000000000000..516ca4f3f77e0 --- /dev/null +++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs @@ -0,0 +1,18 @@ +// Regression test for #66975 +#![warn(const_err)] + +struct PrintName(T); + +impl PrintName { + const VOID: ! = { let x = 0 * std::mem::size_of::(); [][x] }; + //~^ WARN any use of this value will cause an error +} + +fn f() { + let _ = PrintName::::VOID; + //~^ ERROR erroneous constant encountered +} + +pub fn main() { + f::<()>(); +} diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr new file mode 100644 index 0000000000000..e2bd8d0cc85ea --- /dev/null +++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr @@ -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::(); [][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::::VOID; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.rs b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs new file mode 100644 index 0000000000000..b39d9af5546f8 --- /dev/null +++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs @@ -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 +} diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr new file mode 100644 index 0000000000000..c07c8c65a2f20 --- /dev/null +++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr @@ -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`. diff --git a/src/test/ui/consts/const-eval/panic-never-type.rs b/src/test/ui/consts/const-eval/panic-never-type.rs new file mode 100644 index 0000000000000..42eabbf58470f --- /dev/null +++ b/src/test/ui/consts/const-eval/panic-never-type.rs @@ -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 +} diff --git a/src/test/ui/consts/const-eval/panic-never-type.stderr b/src/test/ui/consts/const-eval/panic-never-type.stderr new file mode 100644 index 0000000000000..4fb11a61525f4 --- /dev/null +++ b/src/test/ui/consts/const-eval/panic-never-type.stderr @@ -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`.