From 82cc02a60bc09e31afa6cead8994a9e86b2a8012 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 26 Apr 2024 22:51:16 -0400 Subject: [PATCH] Do not ICE on invalid consts when walking mono-reachable blocks --- compiler/rustc_middle/src/mir/mod.rs | 9 ++---- .../ui/consts/mono-reachable-invalid-const.rs | 23 +++++++++++++++ .../mono-reachable-invalid-const.stderr | 29 +++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 tests/ui/consts/mono-reachable-invalid-const.rs create mode 100644 tests/ui/consts/mono-reachable-invalid-const.stderr diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 43e4e8216e1a6..8555aa48c3069 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -701,10 +701,7 @@ impl<'tcx> Body<'tcx> { env, crate::ty::EarlyBinder::bind(constant.const_), ); - let Some(bits) = mono_literal.try_eval_bits(tcx, env) else { - bug!("Couldn't evaluate constant {:?} in mono {:?}", constant, instance); - }; - bits + mono_literal.try_eval_bits(tcx, env) }; let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else { @@ -714,7 +711,7 @@ impl<'tcx> Body<'tcx> { // If this is a SwitchInt(const _), then we can just evaluate the constant and return. let discr = match discr { Operand::Constant(constant) => { - let bits = eval_mono_const(constant); + let bits = eval_mono_const(constant)?; return Some((bits, targets)); } Operand::Move(place) | Operand::Copy(place) => place, @@ -748,7 +745,7 @@ impl<'tcx> Body<'tcx> { match rvalue { Rvalue::NullaryOp(NullOp::UbChecks, _) => Some((tcx.sess.ub_checks() as u128, targets)), Rvalue::Use(Operand::Constant(constant)) => { - let bits = eval_mono_const(constant); + let bits = eval_mono_const(constant)?; Some((bits, targets)) } _ => None, diff --git a/tests/ui/consts/mono-reachable-invalid-const.rs b/tests/ui/consts/mono-reachable-invalid-const.rs new file mode 100644 index 0000000000000..aabdb071bc9fb --- /dev/null +++ b/tests/ui/consts/mono-reachable-invalid-const.rs @@ -0,0 +1,23 @@ +//@ build-fail + +struct Bar; + +impl Bar { + const ASSERT: bool = { + let b = std::convert::identity(1); + ["oops"][b]; //~ ERROR evaluation of `Bar::<0>::ASSERT` failed + true + }; + + fn assert() { + let val = Self::ASSERT; + if val { + std::convert::identity(val); + } + } +} + + +fn main() { + Bar::<0>::assert(); +} diff --git a/tests/ui/consts/mono-reachable-invalid-const.stderr b/tests/ui/consts/mono-reachable-invalid-const.stderr new file mode 100644 index 0000000000000..6b7b25b59b821 --- /dev/null +++ b/tests/ui/consts/mono-reachable-invalid-const.stderr @@ -0,0 +1,29 @@ +error[E0080]: evaluation of `Bar::<0>::ASSERT` failed + --> $DIR/mono-reachable-invalid-const.rs:8:9 + | +LL | ["oops"][b]; + | ^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + +note: erroneous constant encountered + --> $DIR/mono-reachable-invalid-const.rs:13:19 + | +LL | let val = Self::ASSERT; + | ^^^^^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/mono-reachable-invalid-const.rs:13:19 + | +LL | let val = Self::ASSERT; + | ^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: the above error was encountered while instantiating `fn Bar::<0>::assert` + --> $DIR/mono-reachable-invalid-const.rs:22:5 + | +LL | Bar::<0>::assert(); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`.