diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 6bcfa9d8bf9a7..59981f61b817f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -763,6 +763,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { { // Just point to the function, to reduce the chance of overlapping spans. let function_span = match func { + Operand::RuntimeChecks(_) => span, Operand::Constant(c) => c.span, Operand::Copy(place) | Operand::Move(place) => { if let Some(l) = place.as_local() { @@ -808,6 +809,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { { // Just point to the function, to reduce the chance of overlapping spans. let function_span = match func { + Operand::RuntimeChecks(_) => span, Operand::Constant(c) => c.span, Operand::Copy(place) | Operand::Move(place) => { if let Some(l) = place.as_local() { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 20411fcc16fbb..5845a0bcdf3b1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1559,10 +1559,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { self.consume_operand(location, (operand2, span), state); } - Rvalue::NullaryOp(_op) => { - // nullary ops take no dynamic input; no borrowck effect. - } - Rvalue::Aggregate(aggregate_kind, operands) => { // We need to report back the list of mutable upvars that were // moved into the closure and subsequently used by the closure, @@ -1699,7 +1695,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { _ => propagate_closure_used_mut_place(self, place), } } - Operand::Constant(..) => {} + Operand::Constant(..) | Operand::RuntimeChecks(_) => {} } } @@ -1750,7 +1746,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { state, ); } - Operand::Constant(_) => {} + Operand::Constant(_) | Operand::RuntimeChecks(_) => {} } } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index de479a7d74c8e..d2eae2c7e65a6 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -247,7 +247,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { LocalMutationIsAllowed::Yes, ); } - Operand::Constant(_) => {} + Operand::Constant(_) | Operand::RuntimeChecks(_) => {} } } @@ -314,8 +314,6 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { self.consume_operand(location, operand2); } - Rvalue::NullaryOp(_op) => {} - Rvalue::Aggregate(_, operands) => { for operand in operands { self.consume_operand(location, operand); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 5f86e8646c03f..ec141d41e4fdc 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1023,7 +1023,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // element, so we require the `Copy` trait. if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) { match operand { - Operand::Copy(..) | Operand::Constant(..) => { + Operand::Copy(..) | Operand::Constant(..) | Operand::RuntimeChecks(_) => { // These are always okay: direct use of a const, or a value that can // evidently be copied. } @@ -1046,8 +1046,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } - &Rvalue::NullaryOp(NullOp::RuntimeChecks(_)) => {} - Rvalue::ShallowInitBox(_operand, ty) => { let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [*ty]); @@ -2201,7 +2199,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::Cast(..) | Rvalue::ShallowInitBox(..) | Rvalue::BinaryOp(..) - | Rvalue::NullaryOp(..) | Rvalue::CopyForDeref(..) | Rvalue::UnaryOp(..) | Rvalue::Discriminant(..) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index e445f9457477d..416ab5d76ba9a 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -8,10 +8,10 @@ use rustc_ast::InlineAsmOptions; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_index::IndexVec; -use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; +use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::{ScalarInt, TypeVisitableExt}; use rustc_session::config::OutputFilenames; use rustc_span::Symbol; @@ -853,17 +853,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: fx.bcx.ins().nop(); } } - Rvalue::NullaryOp(ref null_op) => { - assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env())); - let val = match null_op { - NullOp::RuntimeChecks(kind) => kind.value(fx.tcx.sess), - }; - let val = CValue::by_val( - fx.bcx.ins().iconst(types::I8, i64::from(val)), - fx.layout_of(fx.tcx.types.bool), - ); - lval.write_cvalue(fx, val); - } Rvalue::Aggregate(ref kind, ref operands) if matches!(**kind, AggregateKind::RawPtr(..)) => { @@ -1050,6 +1039,12 @@ pub(crate) fn codegen_operand<'tcx>( cplace.to_cvalue(fx) } Operand::Constant(const_) => crate::constant::codegen_constant_operand(fx, const_), + Operand::RuntimeChecks(checks) => { + let int = checks.value(fx.tcx.sess); + let int = ScalarInt::try_from_uint(int, Size::from_bits(1)).unwrap(); + let layout = fx.layout_of(fx.tcx.types.bool); + return CValue::const_val(fx, layout, int); + } } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 2b65b82906818..c25034d4be227 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -540,6 +540,10 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( operand: &Operand<'tcx>, ) -> Option { match operand { + Operand::RuntimeChecks(checks) => { + let int = checks.value(fx.tcx.sess); + ScalarInt::try_from_uint(int, Size::from_bits(1)) + } Operand::Constant(const_) => eval_mir_constant(fx, const_).0.try_to_scalar_int(), // FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored // inside a temporary before being passed to the intrinsic requiring the const argument. diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 5a139702f81d9..aa80812388aff 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -1052,6 +1052,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandRef { move_annotation, ..self.codegen_consume(bx, place.as_ref()) } } + mir::Operand::RuntimeChecks(checks) => { + let layout = bx.layout_of(bx.tcx().types.bool); + let BackendRepr::Scalar(scalar) = layout.backend_repr else { + bug!("from_const: invalid ByVal layout: {:#?}", layout); + }; + let x = Scalar::from_bool(checks.value(bx.tcx().sess)); + let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout)); + let val = OperandValue::Immediate(llval); + OperandRef { val, layout, move_annotation: None } + } + mir::Operand::Constant(ref constant) => { let constant_ty = self.monomorphize(constant.ty()); // Most SIMD vector constants should be passed as immediates. diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 233f9e787398a..d4c4f5c6ec120 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -619,21 +619,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - mir::Rvalue::NullaryOp(ref null_op) => { - let val = match null_op { - mir::NullOp::RuntimeChecks(kind) => { - let val = kind.value(bx.tcx().sess); - bx.cx().const_bool(val) - } - }; - let tcx = self.cx.tcx(); - OperandRef { - val: OperandValue::Immediate(val), - layout: self.cx.layout_of(null_op.ty(tcx)), - move_annotation: None, - } - } - mir::Rvalue::ThreadLocalRef(def_id) => { assert!(bx.cx().tcx().is_static(def_id)); let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id, bx.typing_env())); diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 66a2afa0aa7d0..e7627fd3326de 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -645,7 +645,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Cast(_, _, _) => {} - Rvalue::NullaryOp(NullOp::RuntimeChecks(_)) => {} Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(op, operand) => { diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index f50c6af53bf13..42943648ffdd4 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -230,9 +230,7 @@ where F: FnMut(Local) -> bool, { match rvalue { - Rvalue::ThreadLocalRef(_) | Rvalue::NullaryOp(..) => { - Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)) - } + Rvalue::ThreadLocalRef(_) => Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)), Rvalue::Discriminant(place) => in_place::(cx, in_local, place.as_ref()), @@ -340,6 +338,7 @@ where Operand::Copy(place) | Operand::Move(place) => { return in_place::(cx, in_local, place.as_ref()); } + Operand::RuntimeChecks(_) => return Q::in_any_value_of_ty(cx, cx.tcx.types.bool), Operand::Constant(c) => c, }; diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index e6e3948305af7..d4cc21996aea8 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -198,7 +198,6 @@ where | mir::Rvalue::ThreadLocalRef(..) | mir::Rvalue::Repeat(..) | mir::Rvalue::BinaryOp(..) - | mir::Rvalue::NullaryOp(..) | mir::Rvalue::UnaryOp(..) | mir::Rvalue::Discriminant(..) | mir::Rvalue::Aggregate(..) diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index 438aed41b8be3..f41b68bb1f7ed 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -122,6 +122,13 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine { unimplemented!() } + #[inline(always)] + fn runtime_checks(_ecx: &InterpCx<'tcx, Self>, r: RuntimeChecks) -> InterpResult<'tcx, bool> { + // Runtime checks have different value depending on the crate they are codegenned in. + // Verify we aren't trying to evaluate them in mir-optimizations. + panic!("compiletime machine evaluated {r:?}") + } + fn binary_ptr_op( ecx: &InterpCx<'tcx, Self>, bin_op: BinOp, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index fccb6b171b1c2..12454d6ed68be 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -642,6 +642,16 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { Err(ConstEvalErrKind::AssertFailure(err)).into() } + #[inline(always)] + fn runtime_checks( + _ecx: &InterpCx<'tcx, Self>, + _r: mir::RuntimeChecks, + ) -> InterpResult<'tcx, bool> { + // We can't look at `tcx.sess` here as that can differ across crates, which can lead to + // unsound differences in evaluating the same constant at different instantiation sites. + interp_ok(true) + } + fn binary_ptr_op( _ecx: &InterpCx<'tcx, Self>, _bin_op: mir::BinOp, diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 753b2dd3b8ea1..62ca47d23b4ce 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -298,7 +298,7 @@ pub trait Machine<'tcx>: Sized { interp_ok(()) } - /// Determines the result of a `NullaryOp::RuntimeChecks` invocation. + /// Determines the result of a `Operand::RuntimeChecks` invocation. fn runtime_checks( _ecx: &InterpCx<'tcx, Self>, r: mir::RuntimeChecks, @@ -680,16 +680,6 @@ pub macro compile_time_machine(<$tcx: lifetime>) { true } - #[inline(always)] - fn runtime_checks( - _ecx: &InterpCx<$tcx, Self>, - _r: mir::RuntimeChecks, - ) -> InterpResult<$tcx, bool> { - // We can't look at `tcx.sess` here as that can differ across crates, which can lead to - // unsound differences in evaluating the same constant at different instantiation sites. - interp_ok(true) - } - #[inline(always)] fn adjust_global_allocation<'b>( _ecx: &InterpCx<$tcx, Self>, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index d3d119c8fc9c9..9a956259ba57d 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -845,6 +845,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // FIXME: do some more logic on `move` to invalidate the old location &Copy(place) | &Move(place) => self.eval_place_to_op(place, layout)?, + &RuntimeChecks(checks) => { + let val = M::runtime_checks(self, checks)?; + ImmTy::from_bool(val, self.tcx()).into() + } + Constant(constant) => { let c = self.instantiate_from_current_frame_and_normalize_erasing_regions( constant.const_, diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 8548b774ddb4e..ca8c096d3ab41 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -1,7 +1,6 @@ use either::Either; use rustc_abi::Size; use rustc_apfloat::{Float, FloatConvert}; -use rustc_middle::mir::NullOp; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, FloatTy, ScalarInt}; @@ -505,11 +504,4 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } } - - pub fn nullary_op(&self, null_op: NullOp) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { - use rustc_middle::mir::NullOp::*; - interp_ok(match null_op { - RuntimeChecks(r) => ImmTy::from_bool(M::runtime_checks(self, r)?, *self.tcx), - }) - } } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 88a1160947583..0ef4e4d4ae3c1 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -203,11 +203,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_immediate(*result, &dest)?; } - NullaryOp(null_op) => { - let val = self.nullary_op(null_op)?; - self.write_immediate(*val, &dest)?; - } - Aggregate(box ref kind, ref operands) => { self.write_aggregate(kind, operands, &dest)?; } @@ -392,7 +387,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { move_definitely_disjoint: bool, ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> { interp_ok(match op { - mir::Operand::Copy(_) | mir::Operand::Constant(_) => { + mir::Operand::Copy(_) | mir::Operand::Constant(_) | mir::Operand::RuntimeChecks(_) => { // Make a regular copy. let op = self.eval_operand(op, None)?; FnArg::Copy(op) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4ae4152cfb939..418cdea01660b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -620,6 +620,10 @@ impl<'tcx> Body<'tcx> { let bits = eval_mono_const(constant)?; return Some((bits, targets)); } + Operand::RuntimeChecks(check) => { + let bits = check.value(tcx.sess) as u128; + return Some((bits, targets)); + } Operand::Move(place) | Operand::Copy(place) => place, }; @@ -649,9 +653,6 @@ impl<'tcx> Body<'tcx> { } match rvalue { - Rvalue::NullaryOp(NullOp::RuntimeChecks(kind)) => { - Some((kind.value(tcx.sess) as u128, targets)) - } Rvalue::Use(Operand::Constant(constant)) => { let bits = eval_mono_const(constant)?; Some((bits, targets)) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 3bdc5fdb420c2..ad894527d5750 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1097,15 +1097,6 @@ impl<'tcx> Debug for Rvalue<'tcx> { BinaryOp(ref op, box (ref a, ref b)) => write!(fmt, "{op:?}({a:?}, {b:?})"), UnaryOp(ref op, ref a) => write!(fmt, "{op:?}({a:?})"), Discriminant(ref place) => write!(fmt, "discriminant({place:?})"), - NullaryOp(ref op) => match op { - NullOp::RuntimeChecks(RuntimeChecks::UbChecks) => write!(fmt, "UbChecks()"), - NullOp::RuntimeChecks(RuntimeChecks::ContractChecks) => { - write!(fmt, "ContractChecks()") - } - NullOp::RuntimeChecks(RuntimeChecks::OverflowChecks) => { - write!(fmt, "OverflowChecks()") - } - }, ThreadLocalRef(did) => ty::tls::with(|tcx| { let muta = tcx.static_mutability(did).unwrap().prefix_str(); write!(fmt, "&/*tls*/ {}{}", muta, tcx.def_path_str(did)) @@ -1264,6 +1255,7 @@ impl<'tcx> Debug for Operand<'tcx> { Constant(ref a) => write!(fmt, "{a:?}"), Copy(ref place) => write!(fmt, "copy {place:?}"), Move(ref place) => write!(fmt, "move {place:?}"), + RuntimeChecks(checks) => write!(fmt, "{checks:?}"), } } } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index bd4188dd0ff49..1ba1ae3e1531d 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -642,7 +642,7 @@ impl<'tcx> Operand<'tcx> { pub fn to_copy(&self) -> Self { match *self { - Operand::Copy(_) | Operand::Constant(_) => self.clone(), + Operand::Copy(_) | Operand::Constant(_) | Operand::RuntimeChecks(_) => self.clone(), Operand::Move(place) => Operand::Copy(place), } } @@ -652,7 +652,7 @@ impl<'tcx> Operand<'tcx> { pub fn place(&self) -> Option> { match self { Operand::Copy(place) | Operand::Move(place) => Some(*place), - Operand::Constant(_) => None, + Operand::Constant(_) | Operand::RuntimeChecks(_) => None, } } @@ -661,7 +661,7 @@ impl<'tcx> Operand<'tcx> { pub fn constant(&self) -> Option<&ConstOperand<'tcx>> { match self { Operand::Constant(x) => Some(&**x), - Operand::Copy(_) | Operand::Move(_) => None, + Operand::Copy(_) | Operand::Move(_) | Operand::RuntimeChecks(_) => None, } } @@ -681,6 +681,7 @@ impl<'tcx> Operand<'tcx> { match self { &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, Operand::Constant(c) => c.const_.ty(), + Operand::RuntimeChecks(_) => tcx.types.bool, } } @@ -693,6 +694,8 @@ impl<'tcx> Operand<'tcx> { local_decls.local_decls()[l.local].source_info.span } Operand::Constant(c) => c.span, + // User code should not contain this operand, so we should not need this span. + Operand::RuntimeChecks(_) => DUMMY_SP, } } } @@ -756,7 +759,6 @@ impl<'tcx> Rvalue<'tcx> { _, ) | Rvalue::BinaryOp(_, _) - | Rvalue::NullaryOp(_) | Rvalue::UnaryOp(_, _) | Rvalue::Discriminant(_) | Rvalue::Aggregate(_, _) @@ -794,7 +796,6 @@ impl<'tcx> Rvalue<'tcx> { op.ty(tcx, arg_ty) } Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), - Rvalue::NullaryOp(NullOp::RuntimeChecks(_)) => tcx.types.bool, Rvalue::Aggregate(ref ak, ref ops) => match **ak { AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), AggregateKind::Tuple => { @@ -858,14 +859,6 @@ impl BorrowKind { } } -impl NullOp { - pub fn ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match self { - NullOp::RuntimeChecks(_) => tcx.types.bool, - } - } -} - impl<'tcx> UnOp { pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> { match self { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 204ad4815147b..83e9a1f1784b5 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1327,6 +1327,10 @@ pub enum Operand<'tcx> { /// Constants are already semantically values, and remain unchanged. Constant(Box>), + + /// Query the compilation session of the current crate for a particular flag. This is not quite + /// a const since its value can differ across crates within a single crate graph. + RuntimeChecks(RuntimeChecks), } #[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -1418,9 +1422,6 @@ pub enum Rvalue<'tcx> { /// matching types and return a value of that type. BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>), - /// Computes a value as described by the operation. - NullaryOp(NullOp), - /// Exactly like `BinaryOp`, but less operands. /// /// Also does two's-complement arithmetic. Negation requires a signed integer or a float; @@ -1561,12 +1562,6 @@ pub enum AggregateKind<'tcx> { RawPtr(Ty<'tcx>, Mutability), } -#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] -pub enum NullOp { - /// Returns whether we should perform some checking at runtime. - RuntimeChecks(RuntimeChecks), -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum RuntimeChecks { /// Returns whether we should perform some UB-checking at runtime. diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 7f6c7376501fa..a3c0a5b83ffad 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -293,9 +293,9 @@ pub fn reverse_postorder<'a, 'tcx>( /// reachable. /// /// Such a traversal is mostly useful because it lets us skip lowering the `false` side -/// of `if ::CONST`, as well as [`NullOp::RuntimeChecks`]. +/// of `if ::CONST`, as well as [`Operand::RuntimeChecks`]. /// -/// [`NullOp::RuntimeChecks`]: rustc_middle::mir::NullOp::RuntimeChecks +/// [`Operand::RuntimeChecks`]: rustc_middle::mir::Operand::RuntimeChecks pub fn mono_reachable<'a, 'tcx>( body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 6d251988cbbd8..07a36aef43201 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -775,8 +775,6 @@ macro_rules! make_mir_visitor { ); } - Rvalue::NullaryOp(_op) => {} - Rvalue::Aggregate(kind, operands) => { let kind = &$($mutability)? **kind; match kind { @@ -847,6 +845,7 @@ macro_rules! make_mir_visitor { Operand::Constant(constant) => { self.visit_const_operand(constant, location); } + Operand::RuntimeChecks(_) => {} } } @@ -972,10 +971,7 @@ macro_rules! make_mir_visitor { self.visit_span($(& $mutability)? *span); match const_ { Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location), - Const::Val(_, ty) => { - self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); - } - Const::Unevaluated(_, ty) => { + Const::Val(_, ty) | Const::Unevaluated(_, ty) => { self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index cff415e9036ad..92f81c46ba0d1 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -253,7 +253,6 @@ TrivialTypeTraversalImpls! { crate::mir::FakeReadCause, crate::mir::Local, crate::mir::MirPhase, - crate::mir::NullOp, crate::mir::Promoted, crate::mir::RawPtrKind, crate::mir::RetagKind, @@ -294,6 +293,7 @@ TrivialTypeTraversalImpls! { // interners). TrivialTypeTraversalAndLiftImpls! { // tidy-alphabetical-start + crate::mir::RuntimeChecks, crate::ty::ParamTy, crate::ty::PlaceholderType, crate::ty::instance::ReifyReason, diff --git a/compiler/rustc_mir_build/src/builder/custom/parse.rs b/compiler/rustc_mir_build/src/builder/custom/parse.rs index 10154461c3395..c6ef362c6ea5a 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse.rs @@ -261,6 +261,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { let value = match operand { Operand::Constant(c) => VarDebugInfoContents::Const(*c), Operand::Copy(p) | Operand::Move(p) => VarDebugInfoContents::Place(p), + Operand::RuntimeChecks(_) => unreachable!(), }; let dbginfo = VarDebugInfo { name, diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 9665987362202..a176f3e49a505 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -1099,7 +1099,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Some(DropData { source_info, local, kind: DropKind::Value }) } - Operand::Constant(_) => None, + Operand::Constant(_) | Operand::RuntimeChecks(_) => None, }) .collect(); @@ -1563,7 +1563,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // look for moves of a local variable, like `MOVE(_X)` let locals_moved = operands.iter().flat_map(|operand| match operand.node { - Operand::Copy(_) | Operand::Constant(_) => None, + Operand::Copy(_) | Operand::Constant(_) | Operand::RuntimeChecks(_) => None, Operand::Move(place) => place.as_local(), }); diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 331e41bd126b7..4b2c52ad7999d 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -91,7 +91,6 @@ where | Rvalue::ThreadLocalRef(..) | Rvalue::Repeat(..) | Rvalue::BinaryOp(..) - | Rvalue::NullaryOp(..) | Rvalue::UnaryOp(..) | Rvalue::Discriminant(..) | Rvalue::Aggregate(..) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 0cd3405d1e61b..ced9bd735ba2b 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -448,10 +448,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { } } Rvalue::CopyForDeref(..) => unreachable!(), - Rvalue::Ref(..) - | Rvalue::RawPtr(..) - | Rvalue::Discriminant(..) - | Rvalue::NullaryOp(NullOp::RuntimeChecks(_)) => {} + Rvalue::Ref(..) | Rvalue::RawPtr(..) | Rvalue::Discriminant(..) => {} } } @@ -549,9 +546,10 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { fn gather_operand(&mut self, operand: &Operand<'tcx>) { match *operand { - Operand::Constant(..) | Operand::Copy(..) => {} // not-a-move + // not-a-move + Operand::Constant(..) | Operand::Copy(..) | Operand::RuntimeChecks(_) => {} + // a move Operand::Move(place) => { - // a move self.gather_move(place); } } diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 1a9af0e22bbe2..aaf735269b226 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -60,7 +60,7 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> { } impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { - fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { + fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { // Most costs are in rvalues and terminators, not in statements. match statement.kind { StatementKind::Intrinsic(ref ndi) => { @@ -69,31 +69,8 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { NonDivergingIntrinsic::CopyNonOverlapping(..) => CALL_PENALTY, }; } - _ => self.super_statement(statement, location), - } - } - - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, _location: Location) { - match rvalue { - // FIXME: Should we do the same for `OverflowChecks`? - Rvalue::NullaryOp(NullOp::RuntimeChecks(RuntimeChecks::UbChecks), ..) - if !self - .tcx - .sess - .opts - .unstable_opts - .inline_mir_preserve_debug - .unwrap_or(self.tcx.sess.ub_checks()) => - { - // If this is in optimized MIR it's because it's used later, - // so if we don't need UB checks this session, give a bonus - // here to offset the cost of the call later. - self.bonus += CALL_PENALTY; - } - // These are essentially constants that didn't end up in an Operand, - // so treat them as also being free. - Rvalue::NullaryOp(..) => {} - _ => self.penalty += INSTR_COST, + StatementKind::Assign(..) => self.penalty += INSTR_COST, + _ => {} } } @@ -126,7 +103,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { self.penalty += CALL_PENALTY; } TerminatorKind::SwitchInt { discr, targets } => { - if discr.constant().is_some() { + if matches!(discr, Operand::Constant(_) | Operand::RuntimeChecks(_)) { // Not only will this become a `Goto`, but likely other // things will be removable as unreachable. self.bonus += CONST_SWITCH_BONUS; diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index bccdd526ab7fd..011c10b8bd1db 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -211,6 +211,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { state: &mut State>, ) -> ValueOrPlace> { match operand { + Operand::RuntimeChecks(_) => ValueOrPlace::TOP, Operand::Constant(box constant) => { ValueOrPlace::Value(self.handle_constant(constant, state)) } @@ -463,9 +464,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { FlatSet::Top => FlatSet::Top, } } - Rvalue::NullaryOp(NullOp::RuntimeChecks(_)) => { - return ValueOrPlace::TOP; - } Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map), Rvalue::Use(operand) => return self.handle_operand(operand, state), Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"), @@ -533,6 +531,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { operand: &Operand<'tcx>, ) { match operand { + Operand::RuntimeChecks(_) => {} Operand::Copy(rhs) | Operand::Move(rhs) => { if let Some(rhs) = self.map.find(rhs.as_ref()) { state.insert_place_idx(place, rhs, &self.map); @@ -1039,7 +1038,7 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> { self.super_operand(operand, location) } } - Operand::Constant(_) => {} + Operand::Constant(_) | Operand::RuntimeChecks(_) => {} } } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index da88e5c698bfe..47d735eed9b1f 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -117,11 +117,7 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { unreachable!() }; // Always correct since we can only switch on `Copy` types - let parent_op = match parent_op { - Operand::Move(x) => Operand::Copy(*x), - Operand::Copy(x) => Operand::Copy(*x), - Operand::Constant(x) => Operand::Constant(x.clone()), - }; + let parent_op = parent_op.to_copy(); let parent_ty = parent_op.ty(body.local_decls(), tcx); let statements_before = bbs[parent].statements.len(); let parent_end = Location { block: parent, statement_index: statements_before }; diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 38b5ccdb32e77..2ae8f43cf6c81 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -136,12 +136,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { } fn nth_arg_span(&self, args: &[Spanned>], n: usize) -> Span { - match &args[n].node { - Operand::Copy(place) | Operand::Move(place) => { - self.body.local_decls[place.local].source_info.span - } - Operand::Constant(constant) => constant.span, - } + args[n].node.span(&self.body.local_decls) } fn emit_lint( diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index d9c26faaf4455..4f6416b32e908 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -248,7 +248,7 @@ enum Value<'a, 'tcx> { Discriminant(VnIndex), // Operations. - NullaryOp(NullOp), + RuntimeChecks(RuntimeChecks), UnaryOp(UnOp, VnIndex), BinaryOp(BinOp, VnIndex, VnIndex), Cast { @@ -570,6 +570,8 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { _ if ty.is_zst() => ImmTy::uninit(ty).into(), Opaque(_) => return None, + // Keep runtime check constants as symbolic. + RuntimeChecks(..) => return None, // In general, evaluating repeat expressions just consumes a lot of memory. // But in the special case that the element is just Immediate::Uninit, we can evaluate @@ -682,7 +684,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { self.ecx.discriminant_for_variant(base.layout.ty, variant).discard_err()?; discr_value.into() } - NullaryOp(NullOp::RuntimeChecks(_)) => return None, UnaryOp(un_op, operand) => { let operand = self.eval_to_const(operand)?; let operand = self.ecx.read_immediate(operand).discard_err()?; @@ -1008,11 +1009,16 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { location: Location, ) -> Option { match *operand { + Operand::RuntimeChecks(c) => { + Some(self.insert(self.tcx.types.bool, Value::RuntimeChecks(c))) + } Operand::Constant(ref constant) => Some(self.insert_constant(constant.const_)), Operand::Copy(ref mut place) | Operand::Move(ref mut place) => { let value = self.simplify_place_value(place, location)?; if let Some(const_) = self.try_as_constant(value) { *operand = Operand::Constant(Box::new(const_)); + } else if let Value::RuntimeChecks(c) = self.get(value) { + *operand = Operand::RuntimeChecks(c); } Some(value) } @@ -1035,7 +1041,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { let op = self.simplify_operand(op, location)?; Value::Repeat(op, amount) } - Rvalue::NullaryOp(op) => Value::NullaryOp(op), Rvalue::Aggregate(..) => return self.simplify_aggregate(lhs, rvalue, location), Rvalue::Ref(_, borrow_kind, ref mut place) => { self.simplify_place_projection(place, location); @@ -1781,6 +1786,8 @@ impl<'tcx> VnState<'_, '_, 'tcx> { fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option> { if let Some(const_) = self.try_as_constant(index) { Some(Operand::Constant(Box::new(const_))) + } else if let Value::RuntimeChecks(c) = self.get(index) { + Some(Operand::RuntimeChecks(c)) } else if let Some(place) = self.try_as_place(index, location, false) { self.reused_locals.insert(place.local); Some(Operand::Copy(place)) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 4922d74743c9a..fa9ceb018dd5a 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -4,10 +4,11 @@ use rustc_abi::ExternAbi; use rustc_ast::attr; use rustc_hir::LangItem; use rustc_middle::bug; +use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout}; -use rustc_span::{DUMMY_SP, Symbol, sym}; +use rustc_span::{Symbol, sym}; use crate::simplify::simplify_duplicate_switch_targets; @@ -29,22 +30,22 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let preserve_ub_checks = + attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); + if !preserve_ub_checks { + SimplifyUbCheck { tcx }.visit_body(body); + } let ctx = InstSimplifyContext { tcx, local_decls: &body.local_decls, typing_env: body.typing_env(tcx), }; - let preserve_ub_checks = - attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); for block in body.basic_blocks.as_mut() { for statement in block.statements.iter_mut() { let StatementKind::Assign(box (.., rvalue)) = &mut statement.kind else { continue; }; - if !preserve_ub_checks { - ctx.simplify_ub_check(rvalue); - } ctx.simplify_bool_cmp(rvalue); ctx.simplify_ref_deref(rvalue); ctx.simplify_ptr_aggregate(rvalue); @@ -168,17 +169,6 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } } - fn simplify_ub_check(&self, rvalue: &mut Rvalue<'tcx>) { - // FIXME: Should we do the same for overflow checks? - let Rvalue::NullaryOp(NullOp::RuntimeChecks(RuntimeChecks::UbChecks)) = *rvalue else { - return; - }; - - let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks()); - let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; - *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); - } - fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) { let Rvalue::Cast(kind, operand, cast_ty) = rvalue else { return }; @@ -362,3 +352,26 @@ fn resolve_rust_intrinsic<'tcx>( let intrinsic = tcx.intrinsic(def_id)?; Some((intrinsic.name, args)) } + +struct SimplifyUbCheck<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> MutVisitor<'tcx> for SimplifyUbCheck<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) { + if let Operand::RuntimeChecks(RuntimeChecks::UbChecks) = operand { + *operand = Operand::Constant(Box::new(ConstOperand { + span: rustc_span::DUMMY_SP, + user_ty: None, + const_: Const::Val( + ConstValue::from_bool(self.tcx.sess.ub_checks()), + self.tcx.types.bool, + ), + })); + } + } +} diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 492f5ca82a07e..6bbb505b66b48 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -439,6 +439,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { let Some(rhs) = self.map.find(rhs.as_ref()) else { return }; state.insert_place_idx(rhs, lhs, &self.map); } + Operand::RuntimeChecks(_) => {} } } diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 1f5d31932f1a2..caaf300a88d64 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -282,6 +282,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// or `eval_place`, depending on the variant of `Operand` used. fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option> { match *op { + Operand::RuntimeChecks(_) => None, Operand::Constant(ref c) => self.eval_constant(c), Operand::Move(place) | Operand::Copy(place) => self.eval_place(place), } @@ -444,7 +445,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | Rvalue::Cast(..) | Rvalue::ShallowInitBox(..) | Rvalue::Discriminant(..) - | Rvalue::NullaryOp(..) | Rvalue::WrapUnsafeBinder(..) => {} } @@ -605,8 +605,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Ref(..) | RawPtr(..) => return None, - NullaryOp(NullOp::RuntimeChecks(_)) => return None, - ShallowInitBox(..) => return None, Cast(ref kind, ref value, to) => match kind { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 18b798c01faab..beeed799ee370 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -261,7 +261,7 @@ fn remap_mir_for_const_eval_select<'tcx>( if context == hir::Constness::Const { called_in_const } else { called_at_rt }; let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) = match tupled_args.node { - Operand::Constant(_) => { + Operand::Constant(_) | Operand::RuntimeChecks(_) => { // There is no good way of extracting a tuple arg from a constant // (const generic stuff) so we just create a temporary and deconstruct // that. diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index 2ab49645dc44f..88297a4efef7e 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -88,7 +88,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { | Rvalue::ShallowInitBox(..) | Rvalue::WrapUnsafeBinder(..) => true, Rvalue::ThreadLocalRef(..) - | Rvalue::NullaryOp(..) | Rvalue::UnaryOp(..) | Rvalue::BinaryOp(..) | Rvalue::Ref(..) diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index f25874fbbcb89..dcee54c371080 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -35,7 +35,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.source_info, StatementKind::Assign(Box::new(( *destination, - Rvalue::NullaryOp(NullOp::RuntimeChecks(op)), + Rvalue::Use(Operand::RuntimeChecks(op)), ))), )); terminator.kind = TerminatorKind::Goto { target }; diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 6b0c331ff5415..040822642d969 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -360,6 +360,9 @@ impl<'tcx> Validator<'_, 'tcx> { match operand { Operand::Copy(place) | Operand::Move(place) => self.validate_place(place.as_ref()), + // Promoting a runtime check would transform a runtime error into a compile-time error. + Operand::RuntimeChecks(_) => Err(Unpromotable), + // The qualifs for a constant (e.g. `HasMutInterior`) are checked in // `validate_rvalue` upon access. Operand::Constant(c) => { @@ -449,10 +452,6 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_operand(operand)?; } - Rvalue::NullaryOp(op) => match op { - NullOp::RuntimeChecks(_) => {} - }, - Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), Rvalue::UnaryOp(op, operand) => { diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index ba2286fd40a76..70ae3433353b2 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -41,7 +41,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { { Some(const_operand) } - Operand::Copy(_) | Operand::Move(_) => None, + Operand::Copy(_) | Operand::Move(_) | Operand::RuntimeChecks(_) => None, } } diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 801383493837d..a6ed66c8427b3 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -392,11 +392,14 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { // a_1 = move? place.1 // ... // ``` - StatementKind::Assign(box (lhs, Rvalue::Use(ref op))) => { - let (rplace, copy) = match *op { - Operand::Copy(rplace) => (rplace, true), - Operand::Move(rplace) => (rplace, false), - Operand::Constant(_) => bug!(), + StatementKind::Assign(box ( + lhs, + Rvalue::Use(ref op @ (Operand::Copy(rplace) | Operand::Move(rplace))), + )) => { + let copy = match *op { + Operand::Copy(_) => true, + Operand::Move(_) => false, + Operand::Constant(_) | Operand::RuntimeChecks(_) => bug!(), }; if let Some(final_locals) = self.replacements.place_fragments(lhs) { for (field, ty, new_local) in final_locals { diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 91617be085c31..35d07f4352a24 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1439,7 +1439,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) | Rvalue::RawPtr(_, _) - | Rvalue::NullaryOp(NullOp::RuntimeChecks(_)) | Rvalue::Discriminant(_) => {} Rvalue::WrapUnsafeBinder(op, ty) => { diff --git a/compiler/rustc_public/src/mir/body.rs b/compiler/rustc_public/src/mir/body.rs index fde4d40bea10a..0d4b4b40bfba9 100644 --- a/compiler/rustc_public/src/mir/body.rs +++ b/compiler/rustc_public/src/mir/body.rs @@ -587,9 +587,6 @@ pub enum Rvalue { /// nature of this operation? ThreadLocalRef(crate::CrateItem), - /// Computes a value as described by the operation. - NullaryOp(NullOp), - /// Exactly like `BinaryOp`, but less operands. /// /// Also does two's-complement arithmetic. Negation requires a signed integer or a float; @@ -641,7 +638,6 @@ impl Rvalue { .discriminant_ty() .ok_or_else(|| error!("Expected a `RigidTy` but found: {place_ty:?}")) } - Rvalue::NullaryOp(NullOp::RuntimeChecks(_)) => Ok(Ty::bool_ty()), Rvalue::Aggregate(ak, ops) => match *ak { AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64), AggregateKind::Tuple => Ok(Ty::new_tuple( @@ -677,6 +673,7 @@ pub enum Operand { Copy(Place), Move(Place), Constant(ConstOperand), + RuntimeChecks(RuntimeChecks), } #[derive(Clone, Eq, PartialEq, Hash, Serialize)] @@ -699,6 +696,16 @@ pub struct ConstOperand { pub const_: MirConst, } +#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] +pub enum RuntimeChecks { + /// cfg!(ub_checks), but at codegen time + UbChecks, + /// cfg!(contract_checks), but at codegen time + ContractChecks, + /// cfg!(overflow_checks), but at codegen time + OverflowChecks, +} + /// Debug information pertaining to a user variable. #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct VarDebugInfo { @@ -1018,22 +1025,6 @@ pub enum CastKind { Subtype, } -#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] -pub enum NullOp { - /// Codegen conditions for runtime checks. - RuntimeChecks(RuntimeChecks), -} - -#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] -pub enum RuntimeChecks { - /// cfg!(ub_checks), but at codegen time - UbChecks, - /// cfg!(contract_checks), but at codegen time - ContractChecks, - /// cfg!(overflow_checks), but at codegen time - OverflowChecks, -} - impl Operand { /// Get the type of an operand relative to the local declaration. /// @@ -1045,6 +1036,7 @@ impl Operand { match self { Operand::Copy(place) | Operand::Move(place) => place.ty(locals), Operand::Constant(c) => Ok(c.ty()), + Operand::RuntimeChecks(_) => Ok(Ty::bool_ty()), } } } diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs index d80e227f5a9ce..01dc96f38df1c 100644 --- a/compiler/rustc_public/src/mir/pretty.rs +++ b/compiler/rustc_public/src/mir/pretty.rs @@ -332,6 +332,7 @@ fn pretty_operand(operand: &Operand) -> String { format!("move {mv:?}") } Operand::Constant(cnst) => pretty_mir_const(&cnst.const_), + Operand::RuntimeChecks(checks) => format!("const {checks:?}"), } } @@ -386,9 +387,6 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { Rvalue::ThreadLocalRef(item) => { write!(writer, "thread_local_ref{item:?}") } - Rvalue::NullaryOp(nul) => { - write!(writer, "{nul:?}() \" \"") - } Rvalue::UnaryOp(un, op) => { write!(writer, "{:?}({})", un, pretty_operand(op)) } diff --git a/compiler/rustc_public/src/mir/visit.rs b/compiler/rustc_public/src/mir/visit.rs index 35af39c43a277..678205171ecf2 100644 --- a/compiler/rustc_public/src/mir/visit.rs +++ b/compiler/rustc_public/src/mir/visit.rs @@ -282,7 +282,6 @@ macro_rules! make_mir_visitor { self.visit_operand(op, location) } Rvalue::ThreadLocalRef(_) => {} - Rvalue::NullaryOp(_) => {} Rvalue::UnaryOp(_, op) | Rvalue::Use(op) => { self.visit_operand(op, location); } @@ -297,6 +296,7 @@ macro_rules! make_mir_visitor { Operand::Constant(constant) => { self.visit_const_operand(constant, location); } + Operand::RuntimeChecks(_) => {} } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index e7a1c8218ce4e..a77808cfb275d 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -232,7 +232,6 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { ) } } - NullaryOp(null_op) => crate::mir::Rvalue::NullaryOp(null_op.stable(tables, cx)), UnaryOp(un_op, op) => { crate::mir::Rvalue::UnaryOp(un_op.stable(tables, cx), op.stable(tables, cx)) } @@ -312,21 +311,18 @@ impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind { } } -impl<'tcx> Stable<'tcx> for mir::NullOp { - type T = crate::mir::NullOp; +impl<'tcx> Stable<'tcx> for mir::RuntimeChecks { + type T = crate::mir::RuntimeChecks; fn stable<'cx>( &self, _: &mut Tables<'cx, BridgeTys>, _: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { - use rustc_middle::mir::NullOp::*; use rustc_middle::mir::RuntimeChecks::*; match self { - RuntimeChecks(op) => crate::mir::NullOp::RuntimeChecks(match op { - UbChecks => crate::mir::RuntimeChecks::UbChecks, - ContractChecks => crate::mir::RuntimeChecks::ContractChecks, - OverflowChecks => crate::mir::RuntimeChecks::OverflowChecks, - }), + UbChecks => crate::mir::RuntimeChecks::UbChecks, + ContractChecks => crate::mir::RuntimeChecks::ContractChecks, + OverflowChecks => crate::mir::RuntimeChecks::OverflowChecks, } } } @@ -383,6 +379,7 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> { Copy(place) => crate::mir::Operand::Copy(place.stable(tables, cx)), Move(place) => crate::mir::Operand::Move(place.stable(tables, cx)), Constant(c) => crate::mir::Operand::Constant(c.stable(tables, cx)), + RuntimeChecks(c) => crate::mir::Operand::RuntimeChecks(c.stable(tables, cx)), } } } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index 50e02320748b7..f25781ea8ce5a 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -95,17 +95,16 @@ pub use intrinsics::ub_checks as check_library_ub; #[rustc_allow_const_fn_unstable(const_eval_select)] pub(crate) const fn check_language_ub() -> bool { // Only used for UB checks so we may const_eval_select. - intrinsics::ub_checks() - && const_eval_select!( - @capture { } -> bool: - if const { - // Always disable UB checks. - false - } else { - // Disable UB checks in Miri. - !cfg!(miri) - } - ) + const_eval_select!( + @capture { } -> bool: + if const { + // Always disable UB checks. + false + } else { + // Disable UB checks in Miri. + !cfg!(miri) + } + ) && intrinsics::ub_checks() } /// Checks whether `ptr` is properly aligned with respect to the given alignment, and diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index f2bffc8156afc..0ead5944b4b33 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -110,7 +110,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'_, '_, 'tcx> { immutable_borrowers.push(p.local); } }, - mir::Operand::Constant(..) => (), + mir::Operand::Constant(..) | mir::Operand::RuntimeChecks(..) => (), } } @@ -151,7 +151,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { let mut visit_op = |op: &mir::Operand<'_>| match op { mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local), - mir::Operand::Constant(..) => (), + mir::Operand::Constant(..) | mir::Operand::RuntimeChecks(..) => (), }; match rvalue { diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1fc8e86f3193e..1da8dca3f1ca6 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -13,7 +13,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; use rustc_lint::LateContext; use rustc_middle::mir::{ - Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, + Body, CastKind, NonDivergingIntrinsic, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause}; @@ -194,7 +194,7 @@ fn check_rvalue<'tcx>( )) } }, - Rvalue::NullaryOp(NullOp::RuntimeChecks(_)) | Rvalue::ShallowInitBox(_, _) => Ok(()), + Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, cx.tcx); if ty.is_integral() || ty.is_bool() { @@ -277,6 +277,7 @@ fn check_operand<'tcx>( Some(_) => Err((span, "cannot access `static` items in const fn".into())), None => Ok(()), }, + Operand::RuntimeChecks(..) => Ok(()), } } diff --git a/tests/codegen-llvm/slice-iter-len-eq-zero.rs b/tests/codegen-llvm/slice-iter-len-eq-zero.rs index 6998d98e498c9..3085fbaed36aa 100644 --- a/tests/codegen-llvm/slice-iter-len-eq-zero.rs +++ b/tests/codegen-llvm/slice-iter-len-eq-zero.rs @@ -8,7 +8,7 @@ type Demo = [u8; 3]; #[no_mangle] pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool { // CHECK-NOT: sub - // CHECK: %[[RET:.+]] = icmp eq ptr {{%y.0, %y.1|%y.1, %y.0}} + // CHECK: %[[RET:.+]] = icmp eq ptr {{%0, %1|%1, %0}} // CHECK: ret i1 %[[RET]] y.len() == 0 } @@ -31,7 +31,7 @@ struct MyZST; // CHECK-LABEL: @slice_zst_iter_len_eq_zero #[no_mangle] pub fn slice_zst_iter_len_eq_zero(y: std::slice::Iter<'_, MyZST>) -> bool { - // CHECK: %[[RET:.+]] = icmp eq ptr %y.1, null + // CHECK: %[[RET:.+]] = icmp eq ptr %1, null // CHECK: ret i1 %[[RET]] y.len() == 0 } diff --git a/tests/mir-opt/const_prop/trivial_const.unwrap_unchecked.SimplifyConstCondition-after-inst-simplify.diff b/tests/mir-opt/const_prop/trivial_const.unwrap_unchecked.SimplifyConstCondition-after-inst-simplify.diff index d14c42a330eb7..4714e159396e3 100644 --- a/tests/mir-opt/const_prop/trivial_const.unwrap_unchecked.SimplifyConstCondition-after-inst-simplify.diff +++ b/tests/mir-opt/const_prop/trivial_const.unwrap_unchecked.SimplifyConstCondition-after-inst-simplify.diff @@ -16,7 +16,6 @@ scope 4 (inlined #[track_caller] unreachable_unchecked) { let _5: (); scope 5 (inlined core::ub_checks::check_language_ub) { - let mut _6: bool; scope 6 (inlined core::ub_checks::check_language_ub::runtime) { } } @@ -38,9 +37,7 @@ } bb2: { -- StorageLive(_6); -- _6 = const false; -- assume(copy _6); +- assume(const false); - _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; + unreachable; } diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index 38beb81e1ead2..2aa92fd34ebf2 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -13,7 +13,7 @@ let mut _11: *const (); let mut _16: usize; let mut _17: usize; - let mut _27: usize; + let mut _26: usize; scope 1 { debug vp_ctx => _1; let _5: *const (); @@ -27,7 +27,7 @@ debug _x => _8; } scope 18 (inlined foo) { - let mut _28: *const [()]; + let mut _27: *const [()]; } } scope 16 (inlined slice_from_raw_parts::<()>) { @@ -52,7 +52,7 @@ scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) { scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) { scope 13 (inlined NonNull::<[u8]>::cast::) { - let mut _26: *mut [u8]; + let mut _25: *mut [u8]; scope 14 (inlined NonNull::<[u8]>::as_ptr) { } } @@ -65,9 +65,8 @@ } } scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) { - let mut _23: bool; - let _24: (); - let mut _25: std::ptr::Alignment; + let _23: (); + let mut _24: std::ptr::Alignment; } } } @@ -94,10 +93,8 @@ StorageLive(_20); StorageLive(_21); StorageLive(_22); - StorageLive(_24); StorageLive(_23); - _23 = UbChecks(); - switchInt(move _23) -> [0: bb6, otherwise: bb5]; + switchInt(UbChecks) -> [0: bb6, otherwise: bb5]; } bb1: { @@ -117,14 +114,14 @@ bb4: { _21 = copy ((_19 as Ok).0: std::ptr::NonNull<[u8]>); -- StorageLive(_26); +- StorageLive(_25); + nop; - _26 = copy _21 as *mut [u8] (Transmute); - _12 = copy _26 as *mut u8 (PtrToPtr); -- StorageDead(_26); + _25 = copy _21 as *mut [u8] (Transmute); + _12 = copy _25 as *mut u8 (PtrToPtr); +- StorageDead(_25); + nop; StorageDead(_19); - StorageDead(_24); + StorageDead(_23); StorageDead(_22); StorageDead(_21); StorageDead(_20); @@ -132,7 +129,7 @@ StorageDead(_17); StorageDead(_16); - _13 = copy _12 as *const () (PtrToPtr); -+ _13 = copy _26 as *const () (PtrToPtr); ++ _13 = copy _25 as *const () (PtrToPtr); _14 = NonNull::<()> { pointer: copy _13 }; _15 = Unique::<()> { pointer: copy _14, _marker: const PhantomData::<()> }; _3 = Box::<()>(move _15, const std::alloc::Global); @@ -157,21 +154,21 @@ + nop; StorageLive(_7); _7 = copy _5; - StorageLive(_27); - _27 = const 1_usize; -- _6 = *const [()] from (copy _7, copy _27); + StorageLive(_26); + _26 = const 1_usize; +- _6 = *const [()] from (copy _7, copy _26); + _6 = *const [()] from (copy _5, const 1_usize); - StorageDead(_27); + StorageDead(_26); StorageDead(_7); StorageLive(_8); StorageLive(_9); _9 = copy _6; - StorageLive(_28); -- _28 = copy _9; + StorageLive(_27); +- _27 = copy _9; - _8 = copy _9 as *mut () (PtrToPtr); -+ _28 = copy _6; ++ _27 = copy _6; + _8 = copy _5 as *mut () (PtrToPtr); - StorageDead(_28); + StorageDead(_27); StorageDead(_9); _0 = const (); StorageDead(_8); @@ -183,18 +180,17 @@ } bb5: { -- _24 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable]; -+ _24 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; +- _23 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable]; ++ _23 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_23); - StorageLive(_25); -- _25 = copy _17 as std::ptr::Alignment (Transmute); -- _18 = Layout { size: copy _16, align: move _25 }; -+ _25 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); + StorageLive(_24); +- _24 = copy _17 as std::ptr::Alignment (Transmute); +- _18 = Layout { size: copy _16, align: move _24 }; ++ _24 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); + _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; - StorageDead(_25); + StorageDead(_24); StorageLive(_19); - _19 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _18, const false) -> [return: bb7, unwind unreachable]; + _19 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 047579cdb5094..408ff60712e11 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -13,7 +13,7 @@ let mut _11: *const (); let mut _16: usize; let mut _17: usize; - let mut _27: usize; + let mut _26: usize; scope 1 { debug vp_ctx => _1; let _5: *const (); @@ -27,7 +27,7 @@ debug _x => _8; } scope 18 (inlined foo) { - let mut _28: *const [()]; + let mut _27: *const [()]; } } scope 16 (inlined slice_from_raw_parts::<()>) { @@ -52,7 +52,7 @@ scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) { scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) { scope 13 (inlined NonNull::<[u8]>::cast::) { - let mut _26: *mut [u8]; + let mut _25: *mut [u8]; scope 14 (inlined NonNull::<[u8]>::as_ptr) { } } @@ -65,9 +65,8 @@ } } scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) { - let mut _23: bool; - let _24: (); - let mut _25: std::ptr::Alignment; + let _23: (); + let mut _24: std::ptr::Alignment; } } } @@ -94,10 +93,8 @@ StorageLive(_20); StorageLive(_21); StorageLive(_22); - StorageLive(_24); StorageLive(_23); - _23 = UbChecks(); - switchInt(move _23) -> [0: bb6, otherwise: bb5]; + switchInt(UbChecks) -> [0: bb6, otherwise: bb5]; } bb1: { @@ -117,14 +114,14 @@ bb4: { _21 = copy ((_19 as Ok).0: std::ptr::NonNull<[u8]>); -- StorageLive(_26); +- StorageLive(_25); + nop; - _26 = copy _21 as *mut [u8] (Transmute); - _12 = copy _26 as *mut u8 (PtrToPtr); -- StorageDead(_26); + _25 = copy _21 as *mut [u8] (Transmute); + _12 = copy _25 as *mut u8 (PtrToPtr); +- StorageDead(_25); + nop; StorageDead(_19); - StorageDead(_24); + StorageDead(_23); StorageDead(_22); StorageDead(_21); StorageDead(_20); @@ -132,7 +129,7 @@ StorageDead(_17); StorageDead(_16); - _13 = copy _12 as *const () (PtrToPtr); -+ _13 = copy _26 as *const () (PtrToPtr); ++ _13 = copy _25 as *const () (PtrToPtr); _14 = NonNull::<()> { pointer: copy _13 }; _15 = Unique::<()> { pointer: copy _14, _marker: const PhantomData::<()> }; _3 = Box::<()>(move _15, const std::alloc::Global); @@ -157,21 +154,21 @@ + nop; StorageLive(_7); _7 = copy _5; - StorageLive(_27); - _27 = const 1_usize; -- _6 = *const [()] from (copy _7, copy _27); + StorageLive(_26); + _26 = const 1_usize; +- _6 = *const [()] from (copy _7, copy _26); + _6 = *const [()] from (copy _5, const 1_usize); - StorageDead(_27); + StorageDead(_26); StorageDead(_7); StorageLive(_8); StorageLive(_9); _9 = copy _6; - StorageLive(_28); -- _28 = copy _9; + StorageLive(_27); +- _27 = copy _9; - _8 = copy _9 as *mut () (PtrToPtr); -+ _28 = copy _6; ++ _27 = copy _6; + _8 = copy _5 as *mut () (PtrToPtr); - StorageDead(_28); + StorageDead(_27); StorageDead(_9); _0 = const (); StorageDead(_8); @@ -183,18 +180,17 @@ } bb5: { -- _24 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable]; -+ _24 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; +- _23 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable]; ++ _23 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_23); - StorageLive(_25); -- _25 = copy _17 as std::ptr::Alignment (Transmute); -- _18 = Layout { size: copy _16, align: move _25 }; -+ _25 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); + StorageLive(_24); +- _24 = copy _17 as std::ptr::Alignment (Transmute); +- _18 = Layout { size: copy _16, align: move _24 }; ++ _24 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); + _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; - StorageDead(_25); + StorageDead(_24); StorageLive(_19); - _19 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _18, const false) -> [return: bb7, unwind unreachable]; + _19 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff index 813796657b247..d66223b91bc44 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff @@ -10,7 +10,6 @@ + scope 1 (inlined #[track_caller] core::num::::unchecked_shl) { + let _5: (); + scope 2 (inlined core::ub_checks::check_language_ub) { -+ let mut _6: bool; + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -23,9 +22,7 @@ _4 = copy _2; - _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; + StorageLive(_5); -+ StorageLive(_6); -+ _6 = UbChecks(); -+ switchInt(copy _6) -> [0: bb2, otherwise: bb1]; ++ switchInt(UbChecks) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -34,7 +31,6 @@ + + bb2: { + _0 = ShlUnchecked(copy _3, copy _4); -+ StorageDead(_6); + StorageDead(_5); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff index 61fdb69f74b70..54907cf809b4f 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff @@ -10,7 +10,6 @@ + scope 1 (inlined #[track_caller] core::num::::unchecked_shl) { + let _5: (); + scope 2 (inlined core::ub_checks::check_language_ub) { -+ let mut _6: bool; + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -23,9 +22,7 @@ _4 = copy _2; - _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind continue]; + StorageLive(_5); -+ StorageLive(_6); -+ _6 = UbChecks(); -+ switchInt(copy _6) -> [0: bb2, otherwise: bb1]; ++ switchInt(UbChecks) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -34,7 +31,6 @@ + + bb2: { + _0 = ShlUnchecked(copy _3, copy _4); -+ StorageDead(_6); + StorageDead(_5); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff index 5ea99e8301b80..c118f5b0df3ff 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff @@ -10,7 +10,6 @@ + scope 1 (inlined #[track_caller] core::num::::unchecked_shr) { + let _5: (); + scope 2 (inlined core::ub_checks::check_language_ub) { -+ let mut _6: bool; + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -23,9 +22,7 @@ _4 = copy _2; - _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; + StorageLive(_5); -+ StorageLive(_6); -+ _6 = UbChecks(); -+ switchInt(copy _6) -> [0: bb2, otherwise: bb1]; ++ switchInt(UbChecks) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -34,7 +31,6 @@ + + bb2: { + _0 = ShrUnchecked(copy _3, copy _4); -+ StorageDead(_6); + StorageDead(_5); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff index b13531ab148f2..6a1e6a0a2d26f 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff @@ -10,7 +10,6 @@ + scope 1 (inlined #[track_caller] core::num::::unchecked_shr) { + let _5: (); + scope 2 (inlined core::ub_checks::check_language_ub) { -+ let mut _6: bool; + scope 3 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -23,9 +22,7 @@ _4 = copy _2; - _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind continue]; + StorageLive(_5); -+ StorageLive(_6); -+ _6 = UbChecks(); -+ switchInt(copy _6) -> [0: bb2, otherwise: bb1]; ++ switchInt(UbChecks) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -34,7 +31,6 @@ + + bb2: { + _0 = ShrUnchecked(copy _3, copy _4); -+ StorageDead(_6); + StorageDead(_5); StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index 0119dd799704d..041dd27cb5647 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -12,7 +12,6 @@ + scope 3 (inlined #[track_caller] unreachable_unchecked) { + let _4: (); + scope 4 (inlined core::ub_checks::check_language_ub) { -+ let mut _5: bool; + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -34,9 +33,7 @@ + } + + bb2: { -+ StorageLive(_5); -+ _5 = UbChecks(); -+ assume(copy _5); ++ assume(UbChecks); + _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; + } + diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index d6a5eab1d6e93..be89063a8ac96 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -12,7 +12,6 @@ + scope 3 (inlined #[track_caller] unreachable_unchecked) { + let _4: (); + scope 4 (inlined core::ub_checks::check_language_ub) { -+ let mut _5: bool; + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } @@ -38,9 +37,7 @@ - bb2 (cleanup): { - resume; + bb2: { -+ StorageLive(_5); -+ _5 = UbChecks(); -+ assume(copy _5); ++ assume(UbChecks); + _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; + } + diff --git a/tests/mir-opt/instsimplify/ub_check.rs b/tests/mir-opt/instsimplify/ub_check.rs index b513f60dc7b94..db890c1840798 100644 --- a/tests/mir-opt/instsimplify/ub_check.rs +++ b/tests/mir-opt/instsimplify/ub_check.rs @@ -5,8 +5,7 @@ pub fn unwrap_unchecked(x: Option) -> i32 { // CHECK-LABEL: fn unwrap_unchecked( // CHECK-NOT: UbChecks() - // CHECK: [[assume:_.*]] = const false; - // CHECK-NEXT: assume(copy [[assume]]); + // CHECK: assume(const false); // CHECK-NEXT: unreachable_unchecked::precondition_check unsafe { x.unwrap_unchecked() } } diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff index 2c9071e6e2079..c4fa526a7af99 100644 --- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff @@ -12,7 +12,6 @@ scope 3 (inlined #[track_caller] unreachable_unchecked) { let _4: (); scope 4 (inlined core::ub_checks::check_language_ub) { - let mut _5: bool; scope 5 (inlined core::ub_checks::check_language_ub::runtime) { } } @@ -33,10 +32,8 @@ } bb2: { - StorageLive(_5); -- _5 = UbChecks(); -+ _5 = const false; - assume(copy _5); +- assume(UbChecks); ++ assume(const false); _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; } diff --git a/tests/ui-fulldeps/rustc_public/check_transform.rs b/tests/ui-fulldeps/rustc_public/check_transform.rs index b30d98c3b26f5..8319dd88ca690 100644 --- a/tests/ui-fulldeps/rustc_public/check_transform.rs +++ b/tests/ui-fulldeps/rustc_public/check_transform.rs @@ -69,6 +69,7 @@ fn check_msg(body: &Body, expected: &str) { }) .unwrap() } + Operand::RuntimeChecks(_) => panic!("unexpected runtime checks"), }; let ConstantKind::Allocated(alloc) = msg_const.const_.kind() else { unreachable!()