From d86784c32195bd693b52e227da3047c21e603637 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 3 May 2025 22:58:27 -0600 Subject: [PATCH 1/6] refactor ub_checks and contract_checks to share logic --- compiler/rustc_borrowck/src/type_check/mod.rs | 3 +-- compiler/rustc_codegen_cranelift/src/base.rs | 13 ++----------- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 8 ++------ .../rustc_const_eval/src/check_consts/check.rs | 6 +----- .../rustc_const_eval/src/interpret/machine.rs | 16 +++------------- .../rustc_const_eval/src/interpret/operator.rs | 3 +-- compiler/rustc_middle/src/mir/mod.rs | 4 +++- compiler/rustc_middle/src/mir/pretty.rs | 6 ++++-- compiler/rustc_middle/src/mir/statement.rs | 5 ++--- compiler/rustc_middle/src/mir/syntax.rs | 16 ++++++++++++++++ compiler/rustc_middle/src/mir/traversal.rs | 4 ++-- .../src/move_paths/builder.rs | 6 +----- .../rustc_mir_transform/src/cost_checker.rs | 3 ++- compiler/rustc_mir_transform/src/gvn.rs | 3 +-- .../rustc_mir_transform/src/instsimplify.rs | 3 ++- .../src/known_panics_lint.rs | 3 +-- .../src/lower_intrinsics.rs | 18 ++++++------------ .../rustc_mir_transform/src/promote_consts.rs | 3 +-- compiler/rustc_mir_transform/src/validate.rs | 5 +---- .../rustc_smir/src/rustc_smir/convert/mir.rs | 7 +++++-- compiler/rustc_smir/src/stable_mir/mir/body.rs | 9 +++++++-- .../clippy_utils/src/qualify_min_const_fn.rs | 5 +---- src/tools/miri/src/machine.rs | 9 ++------- 23 files changed, 67 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8c51225712093..069fea01b1728 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1040,8 +1040,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ConstraintCategory::SizedBound, ); } - &Rvalue::NullaryOp(NullOp::ContractChecks, _) => {} - &Rvalue::NullaryOp(NullOp::UbChecks, _) => {} + &Rvalue::NullaryOp(NullOp::RuntimeChecks(_), _) => {} Rvalue::ShallowInitBox(_operand, ty) => { let trait_ref = ty::TraitRef::new( diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 524e0d9fe35ed..0f69261ce1615 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -836,17 +836,8 @@ fn codegen_stmt<'tcx>( fields.iter(), ) .bytes(), - NullOp::UbChecks => { - let val = fx.tcx.sess.ub_checks(); - 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); - return; - } - NullOp::ContractChecks => { - let val = fx.tcx.sess.contract_checks(); + NullOp::RuntimeChecks(kind) => { + let val = 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), diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 5c14fe5cd10b7..f1140cd02cb8d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -752,12 +752,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .bytes(); bx.cx().const_usize(val) } - mir::NullOp::UbChecks => { - let val = bx.tcx().sess.ub_checks(); - bx.cx().const_bool(val) - } - mir::NullOp::ContractChecks => { - let val = bx.tcx().sess.contract_checks(); + mir::NullOp::RuntimeChecks(kind) => { + let val = kind.value(bx.tcx().sess); bx.cx().const_bool(val) } }; diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index b600b8918dd01..315f307789e23 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -675,11 +675,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Cast(_, _, _) => {} Rvalue::NullaryOp( - NullOp::SizeOf - | NullOp::AlignOf - | NullOp::OffsetOf(_) - | NullOp::UbChecks - | NullOp::ContractChecks, + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::RuntimeChecks(_), _, ) => {} Rvalue::ShallowInitBox(_, _) => {} diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index a1386b4e1be49..b848ef3838bd7 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -296,11 +296,8 @@ pub trait Machine<'tcx>: Sized { interp_ok(()) } - /// Determines the result of a `NullaryOp::UbChecks` invocation. - fn ub_checks(_ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool>; - - /// Determines the result of a `NullaryOp::ContractChecks` invocation. - fn contract_checks(_ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool>; + /// Determines the result of a `NullaryOp::RuntimeChecks` invocation. + fn runtime_checks(_ecx: &InterpCx<'tcx, Self>, r: mir::RuntimeChecks) -> InterpResult<'tcx, bool>; /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction. /// You can use this to detect long or endlessly running programs. @@ -677,14 +674,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) { } #[inline(always)] - fn ub_checks(_ecx: &InterpCx<$tcx, Self>) -> 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 contract_checks(_ecx: &InterpCx<$tcx, Self>) -> InterpResult<$tcx, bool> { + 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) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 899670aeb62da..7462614a7fee8 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -536,8 +536,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.tcx.offset_of_subfield(self.typing_env, layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } - UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), - ContractChecks => ImmTy::from_bool(M::contract_checks(self)?, *self.tcx), + RuntimeChecks(r) => ImmTy::from_bool(M::runtime_checks(self, r)?, *self.tcx), }) } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index adc100941a39a..f9b5bf0645fe9 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -692,7 +692,9 @@ impl<'tcx> Body<'tcx> { } match rvalue { - Rvalue::NullaryOp(NullOp::UbChecks, _) => Some((tcx.sess.ub_checks() as u128, targets)), + 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 57ae7dc55c5c8..2a1ebc1b20023 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1134,8 +1134,10 @@ impl<'tcx> Debug for Rvalue<'tcx> { NullOp::SizeOf => write!(fmt, "SizeOf({t})"), NullOp::AlignOf => write!(fmt, "AlignOf({t})"), NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"), - NullOp::UbChecks => write!(fmt, "UbChecks()"), - NullOp::ContractChecks => write!(fmt, "ContractChecks()"), + NullOp::RuntimeChecks(RuntimeChecks::UbChecks) => write!(fmt, "UbChecks()"), + NullOp::RuntimeChecks(RuntimeChecks::ContractChecks) => { + write!(fmt, "ContractChecks()") + } } } ThreadLocalRef(did) => ty::tls::with(|tcx| { diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index d59b6df44ed5d..3cc3205260e39 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -709,8 +709,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { tcx.types.usize } - Rvalue::NullaryOp(NullOp::ContractChecks, _) - | Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool, + 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 => { @@ -778,7 +777,7 @@ impl<'tcx> NullOp<'tcx> { pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self { NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) => tcx.types.usize, - NullOp::UbChecks | NullOp::ContractChecks => tcx.types.bool, + NullOp::RuntimeChecks(_) => tcx.types.bool, } } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index bb068f3821db8..fc729618d50c8 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1588,6 +1588,12 @@ pub enum NullOp<'tcx> { AlignOf, /// Returns the offset of a field OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>), + /// 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. /// See the `ub_checks` intrinsic docs for details. UbChecks, @@ -1596,6 +1602,16 @@ pub enum NullOp<'tcx> { ContractChecks, } +impl RuntimeChecks { + pub fn value(self, sess: &rustc_session::Session) -> bool { + match self { + Self::UbChecks => sess.ub_checks(), + Self::ContractChecks => sess.contract_checks(), + Self::OverflowChecks => sess.overflow_checks(), + } + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub enum UnOp { diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 9308570d89d18..7f6c7376501fa 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::UbChecks`]. +/// of `if ::CONST`, as well as [`NullOp::RuntimeChecks`]. /// -/// [`NullOp::UbChecks`]: rustc_middle::mir::NullOp::UbChecks +/// [`NullOp::RuntimeChecks`]: rustc_middle::mir::NullOp::RuntimeChecks pub fn mono_reachable<'a, 'tcx>( body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 8bbc89fdcecb7..259ecd5c82fe1 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -416,11 +416,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | Rvalue::Discriminant(..) | Rvalue::Len(..) | Rvalue::NullaryOp( - NullOp::SizeOf - | NullOp::AlignOf - | NullOp::OffsetOf(..) - | NullOp::UbChecks - | NullOp::ContractChecks, + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::RuntimeChecks(_), _, ) => {} } diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 00a8293966b04..1a9af0e22bbe2 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -75,7 +75,8 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, _location: Location) { match rvalue { - Rvalue::NullaryOp(NullOp::UbChecks, ..) + // FIXME: Should we do the same for `OverflowChecks`? + Rvalue::NullaryOp(NullOp::RuntimeChecks(RuntimeChecks::UbChecks), ..) if !self .tcx .sess diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 8b8d1efbbd2e0..8266686a52864 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -538,8 +538,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { .tcx .offset_of_subfield(self.typing_env(), layout, fields.iter()) .bytes(), - NullOp::UbChecks => return None, - NullOp::ContractChecks => return None, + NullOp::RuntimeChecks(_) => return None, }; let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); let imm = ImmTy::from_uint(val, usize_layout); diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 5f0c55ddc092d..b019ecf3e7322 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -168,7 +168,8 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } fn simplify_ub_check(&self, rvalue: &mut Rvalue<'tcx>) { - let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue else { return }; + // 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 }; diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 481c794190925..32c45c3842d31 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -629,8 +629,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { .tcx .offset_of_subfield(self.typing_env, op_layout, fields.iter()) .bytes(), - NullOp::UbChecks => return None, - NullOp::ContractChecks => return None, + NullOp::RuntimeChecks(_) => return None, }; ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into() } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 9c21bcfc0d26a..b1f13fc3546f9 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -24,23 +24,17 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Unreachable; } sym::ub_checks => { + let op = match intrinsic.name { + sym::ub_checks => RuntimeChecks::UbChecks, + sym::contract_checks => RuntimeChecks::ContractChecks, + _ => unreachable!(), + }; let target = target.unwrap(); block.statements.push(Statement { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::NullaryOp(NullOp::UbChecks, tcx.types.bool), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } - sym::contract_checks => { - let target = target.unwrap(); - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::NullaryOp(NullOp::ContractChecks, tcx.types.bool), + Rvalue::NullaryOp(NullOp::RuntimeChecks(op), tcx.types.bool), ))), }); 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 47d4383097008..6b8cc006dd659 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -456,8 +456,7 @@ impl<'tcx> Validator<'_, 'tcx> { NullOp::SizeOf => {} NullOp::AlignOf => {} NullOp::OffsetOf(_) => {} - NullOp::UbChecks => {} - NullOp::ContractChecks => {} + NullOp::RuntimeChecks(_) => {} }, Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index f541a32cd2645..5f7373a9d5b12 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1390,10 +1390,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) | Rvalue::RawPtr(_, _) - | Rvalue::NullaryOp( - NullOp::SizeOf | NullOp::AlignOf | NullOp::UbChecks | NullOp::ContractChecks, - _, - ) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::RuntimeChecks(_), _) | Rvalue::Discriminant(_) => {} Rvalue::WrapUnsafeBinder(op, ty) => { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 42b3e59b73ab9..50037df608cd4 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -285,14 +285,17 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { type T = stable_mir::mir::NullOp; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { use rustc_middle::mir::NullOp::*; + use rustc_middle::mir::RuntimeChecks::*; match self { SizeOf => stable_mir::mir::NullOp::SizeOf, AlignOf => stable_mir::mir::NullOp::AlignOf, OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf( indices.iter().map(|idx| idx.stable(tables)).collect(), ), - UbChecks => stable_mir::mir::NullOp::UbChecks, - ContractChecks => stable_mir::mir::NullOp::ContractChecks, + RuntimeChecks(kind) => stable_mir::mir::NullOp::RuntimeChecks(match kind { + UbChecks => stable_mir::mir::RuntimeChecks::UbChecks, + ContractChecks => stable_mir::mir::RuntimeChecks::ContractChecks, + }), } } } diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 660cd7db0800d..4651c1421b2dc 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -642,8 +642,7 @@ impl Rvalue { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { Ok(Ty::usize_ty()) } - Rvalue::NullaryOp(NullOp::ContractChecks, _) - | Rvalue::NullaryOp(NullOp::UbChecks, _) => Ok(Ty::bool_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( @@ -1040,6 +1039,12 @@ pub enum NullOp { AlignOf, /// Returns the offset of a field. OffsetOf(Vec<(VariantIdx, FieldIdx)>), + /// Codegen conditions for runtime checks. + RuntimeChecks(RuntimeChecks), +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +pub enum RuntimeChecks { /// cfg!(ub_checks), but at codegen time UbChecks, /// cfg!(contract_checks), but at codegen time 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 5d0401010db6a..01315121abe53 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 @@ -182,10 +182,7 @@ fn check_rvalue<'tcx>( )) } }, - Rvalue::NullaryOp( - NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbChecks | NullOp::ContractChecks, - _, - ) + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::RuntimeChecks(_), _) | Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, cx.tcx); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 55aa3d6fa6873..3cd0f451814d1 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1214,13 +1214,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } #[inline(always)] - fn ub_checks(ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool> { - interp_ok(ecx.tcx.sess.ub_checks()) - } - - #[inline(always)] - fn contract_checks(ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool> { - interp_ok(ecx.tcx.sess.contract_checks()) + fn runtime_checks(ecx: &InterpCx<'tcx, Self>, r: mir::RuntimeChecks) -> InterpResult<'tcx, bool> { + interp_ok(r.value(&ecx.tcx.sess)) } #[inline(always)] From a2d97d370f3eb4e2923aff4490f8d1d10c8b59b3 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 3 Aug 2024 22:57:10 -0600 Subject: [PATCH 2/6] add `overflow_checks` intrinsic --- .../rustc_hir_analysis/src/check/intrinsic.rs | 3 +- compiler/rustc_middle/src/mir/pretty.rs | 3 ++ compiler/rustc_middle/src/mir/syntax.rs | 3 ++ .../src/lower_intrinsics.rs | 3 +- .../rustc_smir/src/rustc_smir/convert/mir.rs | 1 + .../rustc_smir/src/stable_mir/mir/body.rs | 2 ++ library/core/src/intrinsics/mod.rs | 20 +++++++++++++ .../codegen/auxiliary/overflow_checks_add.rs | 14 +++++++++ tests/codegen/overflow-checks.rs | 29 +++++++++++++++++++ 9 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/codegen/auxiliary/overflow_checks_add.rs create mode 100644 tests/codegen/overflow-checks.rs diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 692784bf1714d..3807330a7fbdf 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -120,6 +120,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::contract_checks | sym::contract_check_requires | sym::contract_check_ensures + | sym::overflow_checks | sym::fadd_algebraic | sym::fsub_algebraic | sym::fmul_algebraic @@ -591,7 +592,7 @@ pub(crate) fn check_intrinsic_type( sym::aggregate_raw_ptr => (3, 0, vec![param(1), param(2)], param(0)), sym::ptr_metadata => (2, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(1)), - sym::ub_checks => (0, 0, Vec::new(), tcx.types.bool), + sym::ub_checks | sym::overflow_checks => (0, 0, Vec::new(), tcx.types.bool), sym::box_new => (1, 0, vec![param(0)], Ty::new_box(tcx, param(0))), diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 2a1ebc1b20023..94b37638081da 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1138,6 +1138,9 @@ impl<'tcx> Debug for Rvalue<'tcx> { NullOp::RuntimeChecks(RuntimeChecks::ContractChecks) => { write!(fmt, "ContractChecks()") } + NullOp::RuntimeChecks(RuntimeChecks::OverflowChecks) => { + write!(fmt, "OverflowChecks()") + } } } ThreadLocalRef(did) => ty::tls::with(|tcx| { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index fc729618d50c8..0447b8a52d950 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1600,6 +1600,9 @@ pub enum RuntimeChecks { /// Returns whether we should perform contract-checking at runtime. /// See the `contract_checks` intrinsic docs for details. ContractChecks, + /// Returns whether we should perform some overflow-checking at runtime. + /// See the `overflow_checks` intrinsic docs for details. + OverflowChecks, } impl RuntimeChecks { diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index b1f13fc3546f9..8e2f0315dd05d 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -23,10 +23,11 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { sym::unreachable => { terminator.kind = TerminatorKind::Unreachable; } - sym::ub_checks => { + sym::ub_checks | sym::overflow_checks => { let op = match intrinsic.name { sym::ub_checks => RuntimeChecks::UbChecks, sym::contract_checks => RuntimeChecks::ContractChecks, + sym::overflow_checks => RuntimeChecks::OverflowChecks, _ => unreachable!(), }; let target = target.unwrap(); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 50037df608cd4..fe1618c6174de 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -295,6 +295,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { RuntimeChecks(kind) => stable_mir::mir::NullOp::RuntimeChecks(match kind { UbChecks => stable_mir::mir::RuntimeChecks::UbChecks, ContractChecks => stable_mir::mir::RuntimeChecks::ContractChecks, + OverflowChecks => stable_mir::mir::RuntimeChecks::OverflowChecks, }), } } diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 4651c1421b2dc..70cf4356a674e 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1049,6 +1049,8 @@ pub enum RuntimeChecks { UbChecks, /// cfg!(contract_checks), but at codegen time ContractChecks, + /// cfg!(overflow_checks), but at codegen time + OverflowChecks, } impl Operand { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index c5d5bc000f1c7..be7eda4229410 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3346,6 +3346,26 @@ pub const unsafe fn typed_swap_nonoverlapping(x: *mut T, y: *mut T) { pub const fn ub_checks() -> bool { cfg!(ub_checks) } +/// Returns whether we should perform some overflow-checking at runtime. This eventually evaluates to +/// `cfg!(overflow_checks)`, but behaves different from `cfg!` when mixing crates built with different +/// flags: if the crate has UB checks enabled or carries the `#[rustc_preserve_overflow_checks]` +/// attribute, evaluation is delayed until monomorphization (or until the call gets inlined into +/// a crate that does not delay evaluation further); otherwise it can happen any time. +/// +/// The common case here is a user program built with overflow_checks linked against the distributed +/// sysroot which is built without overflow_checks but with `#[rustc_preserve_overflow_checks]`. +/// For code that gets monomorphized in the user crate (i.e., generic functions and functions with +/// `#[inline]`), gating assertions on `overflow_checks()` rather than `cfg!(overflow_checks)` means that +/// assertions are enabled whenever the *user crate* has UB checks enabled. However if the +/// user has overflow checks disabled, the checks will still get optimized out. +#[cfg(not(bootstrap))] +#[rustc_const_unstable(feature = "const_overflow_checks", issue = "none")] +#[unstable(feature = "const_overflow_checks", issue = "none")] +#[inline(always)] +#[rustc_intrinsic] +pub const fn overflow_checks() -> bool { + cfg!(debug_assertions) +} /// Allocates a block of memory at compile time. /// At runtime, just returns a null pointer. diff --git a/tests/codegen/auxiliary/overflow_checks_add.rs b/tests/codegen/auxiliary/overflow_checks_add.rs new file mode 100644 index 0000000000000..3402f59f94692 --- /dev/null +++ b/tests/codegen/auxiliary/overflow_checks_add.rs @@ -0,0 +1,14 @@ +//@ compile-flags: -Cdebug-assertions=yes + +#![crate_type = "lib"] +#![feature(strict_overflow_ops)] +#![feature(rustc_attrs)] +#![feature(core_intrinsics)] + +/// Emulates the default behavior of `+` using +/// `intrinsics::overflow_checks()`. +#[inline] +#[rustc_inherit_overflow_checks] +pub fn add(a: u8, b: u8) -> u8 { + if core::intrinsics::overflow_checks() { a.strict_add(b) } else { a.wrapping_add(b) } +} diff --git a/tests/codegen/overflow-checks.rs b/tests/codegen/overflow-checks.rs new file mode 100644 index 0000000000000..fb6090e9195b3 --- /dev/null +++ b/tests/codegen/overflow-checks.rs @@ -0,0 +1,29 @@ +// With -Coverflow-checks=yes (enabled by default by -Cdebug-assertions=yes) we will produce a +// runtime check that panics when an operation would result in integer overflow. +// +// This test ensures that such a runtime check is *not* emitted when debug-assertions are enabled, +// but overflow-checks are explicitly disabled. It also ensures that even if a dependency is +// compiled with overflow checks, `intrinsics::overflow_checks()` will be treated with the +// overflow-checks setting of the current crate (when `#[rustc_inherit_overflow_checks]`) is used. + +//@ aux-build:overflow_checks_add.rs +//@ revisions: DEBUG NOCHECKS +//@ [DEBUG] compile-flags: +//@ [NOCHECKS] compile-flags: -Coverflow-checks=no +//@ compile-flags: -O -Cdebug-assertions=yes + +#![crate_type = "lib"] + +extern crate overflow_checks_add; + +// CHECK-LABEL: @add( +#[no_mangle] +pub unsafe fn add(a: u8, b: u8) -> u8 { + // CHECK: i8 noundef %a, i8 noundef %b + // DEBUG: @llvm.uadd.with.overflow.i8 + // DEBUG: call core::num::overflow_panic::add + // DEBUG: unreachable + // NOCHECKS: %0 = add i8 %b, %a + // NOCHECKS: ret i8 %0 + overflow_checks_add::add(a, b) +} From 5ffc73ffed3156a44e17a35163b8f6bcf2636550 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 3 May 2025 23:03:47 -0600 Subject: [PATCH 3/6] fix a couple unstable attributes --- library/core/src/range/iter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs index 1e261d8c1d93a..f62f4ed72cc66 100644 --- a/library/core/src/range/iter.rs +++ b/library/core/src/range/iter.rs @@ -168,7 +168,7 @@ impl IterRangeInclusive { } } -#[unstable(feature = "trusted_random_access", issue = "none")] +#[unstable(feature = "new_range_api", issue = "125687")] impl Iterator for IterRangeInclusive { type Item = A; @@ -302,7 +302,7 @@ impl IterRangeFrom { } } -#[unstable(feature = "trusted_random_access", issue = "none")] +#[unstable(feature = "new_range_api", issue = "125687")] impl Iterator for IterRangeFrom { type Item = A; From 94cb3c2a5673cc140b738ff7943e27ea0141a123 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 3 May 2025 23:32:17 -0600 Subject: [PATCH 4/6] new RangeFrom overflow check --- library/core/src/range/iter.rs | 63 ++++++++++++++++--- .../codegen/iterrangefrom-overflow-checks.rs | 29 +++++++++ tests/ui/iterators/iterrangefrom.rs | 23 +++++++ .../ui/iterators/rangefrom-overflow-debug.rs | 17 +++++ .../ui/iterators/rangefrom-overflow-ndebug.rs | 10 +++ .../rangefrom-overflow-overflow-checks.rs | 17 +++++ 6 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 tests/codegen/iterrangefrom-overflow-checks.rs create mode 100644 tests/ui/iterators/iterrangefrom.rs create mode 100644 tests/ui/iterators/rangefrom-overflow-debug.rs create mode 100644 tests/ui/iterators/rangefrom-overflow-ndebug.rs create mode 100644 tests/ui/iterators/rangefrom-overflow-overflow-checks.rs diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs index f62f4ed72cc66..07c42cd99ee77 100644 --- a/library/core/src/range/iter.rs +++ b/library/core/src/range/iter.rs @@ -1,6 +1,9 @@ +#[cfg(not(bootstrap))] +use crate::intrinsics; use crate::iter::{ FusedIterator, Step, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep, }; +use crate::mem; use crate::num::NonZero; use crate::range::{Range, RangeFrom, RangeInclusive, legacy}; @@ -293,12 +296,27 @@ range_incl_exact_iter_impl! { /// By-value [`RangeFrom`] iterator. #[unstable(feature = "new_range_api", issue = "125687")] #[derive(Debug, Clone)] -pub struct IterRangeFrom(legacy::RangeFrom); +pub struct IterRangeFrom { + start: A, + #[allow(dead_code)] + /// Whether the first element of the iterator has yielded. + /// Only used when overflow checks are enabled. + first: bool, +} -impl IterRangeFrom { +impl IterRangeFrom { /// Returns the remainder of the range being iterated over. + #[inline] + #[rustc_inherit_overflow_checks] pub fn remainder(self) -> RangeFrom { - RangeFrom { start: self.0.start } + #[cfg(not(bootstrap))] + if intrinsics::overflow_checks() { + if !self.first { + return RangeFrom { start: Step::forward(self.start, 1) }; + } + } + + RangeFrom { start: self.start } } } @@ -307,18 +325,49 @@ impl Iterator for IterRangeFrom { type Item = A; #[inline] + #[rustc_inherit_overflow_checks] fn next(&mut self) -> Option { - self.0.next() + #[cfg(not(bootstrap))] + if intrinsics::overflow_checks() { + if self.first { + self.first = false; + return Some(self.start.clone()); + } + + self.start = Step::forward(self.start.clone(), 1); + return Some(self.start.clone()); + } + + let n = Step::forward(self.start.clone(), 1); + Some(mem::replace(&mut self.start, n)) } #[inline] fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() + (usize::MAX, None) } #[inline] + #[rustc_inherit_overflow_checks] fn nth(&mut self, n: usize) -> Option { - self.0.nth(n) + #[cfg(not(bootstrap))] + if intrinsics::overflow_checks() { + if self.first { + self.first = false; + + let plus_n = Step::forward(self.start.clone(), n); + self.start = plus_n.clone(); + return Some(plus_n); + } + + let plus_n = Step::forward(self.start.clone(), n); + self.start = Step::forward(plus_n.clone(), 1); + return Some(self.start.clone()); + } + + let plus_n = Step::forward(self.start.clone(), n); + self.start = Step::forward(plus_n.clone(), 1); + Some(plus_n) } } @@ -334,6 +383,6 @@ impl IntoIterator for RangeFrom { type IntoIter = IterRangeFrom; fn into_iter(self) -> Self::IntoIter { - IterRangeFrom(self.into()) + IterRangeFrom { start: self.start, first: true } } } diff --git a/tests/codegen/iterrangefrom-overflow-checks.rs b/tests/codegen/iterrangefrom-overflow-checks.rs new file mode 100644 index 0000000000000..14c0f41d958e5 --- /dev/null +++ b/tests/codegen/iterrangefrom-overflow-checks.rs @@ -0,0 +1,29 @@ +// With -Coverflow-checks=yes (enabled by default by -Cdebug-assertions=yes) we will produce a +// runtime check that panics after yielding the maximum value of the range bound type. That is +// tested for by tests/ui/iterators/rangefrom-overflow-overflow-checks.rs +// +// This test ensures that such a runtime check is *not* emitted when debug-assertions are +// enabled, but overflow-checks are explicitly disabled. + +//@ revisions: DEBUG NOCHECKS +//@ [DEBUG] compile-flags: +//@ [NOCHECKS] compile-flags: -Coverflow-checks=no +//@ compile-flags: -O -Cdebug-assertions=yes + +#![crate_type = "lib"] + +#![feature(new_range_api)] +use std::range::{RangeFrom, IterRangeFrom}; + +// CHECK-LABEL: @iterrangefrom_remainder( +#[no_mangle] +pub unsafe fn iterrangefrom_remainder(x: IterRangeFrom) -> RangeFrom { + // DEBUG: i32 noundef %x.0 + // NOCHECKS: i32 noundef returned %x.0 + // CHECK: i1 noundef zeroext %x.1 + // DEBUG: br i1 + // DEBUG: call core::panicking::panic_const::panic_const_add_overflow + // DEBUG: unreachable + // NOCHECKS: ret i32 %x.0 + x.remainder() +} diff --git a/tests/ui/iterators/iterrangefrom.rs b/tests/ui/iterators/iterrangefrom.rs new file mode 100644 index 0000000000000..54d8f522a2c88 --- /dev/null +++ b/tests/ui/iterators/iterrangefrom.rs @@ -0,0 +1,23 @@ +//@ run-pass +//@ compile-flags: -C overflow-checks=yes + +#![feature(new_range_api)] + +use std::{iter, range}; + +fn main() { + for (a, b) in iter::zip(0_u32..256, range::RangeFrom::from(0_u8..)) { + assert_eq!(a, u32::from(b)); + } + + let mut a = range::RangeFrom::from(0_u8..).into_iter(); + let mut b = 0_u8..; + assert_eq!(a.next(), b.next()); + assert_eq!(a.nth(5), b.nth(5)); + assert_eq!(a.nth(0), b.next()); + + let mut a = range::RangeFrom::from(0_u8..).into_iter(); + let mut b = 0_u8..; + assert_eq!(a.nth(5), b.nth(5)); + assert_eq!(a.nth(0), b.next()); +} diff --git a/tests/ui/iterators/rangefrom-overflow-debug.rs b/tests/ui/iterators/rangefrom-overflow-debug.rs new file mode 100644 index 0000000000000..9a1bc6910a044 --- /dev/null +++ b/tests/ui/iterators/rangefrom-overflow-debug.rs @@ -0,0 +1,17 @@ +//@ run-pass +//@ needs-unwind +//@ compile-flags: -O -C debug_assertions=yes + +#![feature(new_range_api)] + +use std::panic; + +fn main() { + let mut it = core::range::RangeFrom::from(u8::MAX..).into_iter(); + assert_eq!(it.next().unwrap(), 255); + + let r = panic::catch_unwind(|| { + let _ = it.remainder(); + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/rangefrom-overflow-ndebug.rs b/tests/ui/iterators/rangefrom-overflow-ndebug.rs new file mode 100644 index 0000000000000..4ce9b0636383c --- /dev/null +++ b/tests/ui/iterators/rangefrom-overflow-ndebug.rs @@ -0,0 +1,10 @@ +//@ run-pass +//@ compile-flags: -O -C debug_assertions=no + +#![feature(new_range_api)] + +fn main() { + let mut it = core::range::RangeFrom::from(u8::MAX..).into_iter(); + assert_eq!(it.next().unwrap(), 255); + assert_eq!(it.remainder().start, u8::MIN); +} diff --git a/tests/ui/iterators/rangefrom-overflow-overflow-checks.rs b/tests/ui/iterators/rangefrom-overflow-overflow-checks.rs new file mode 100644 index 0000000000000..cafd4dd0ed428 --- /dev/null +++ b/tests/ui/iterators/rangefrom-overflow-overflow-checks.rs @@ -0,0 +1,17 @@ +//@ run-pass +//@ needs-unwind +//@ compile-flags: -O -C overflow-checks=yes + +#![feature(new_range_api)] + +use std::panic; + +fn main() { + let mut it = core::range::RangeFrom::from(u8::MAX..).into_iter(); + assert_eq!(it.next().unwrap(), 255); + + let r = panic::catch_unwind(|| { + let _ = it.remainder(); + }); + assert!(r.is_err()); +} From e915b4b91e3751c5174c6700f421790cf8b5ba94 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 3 May 2025 23:52:03 -0600 Subject: [PATCH 5/6] (intentionally broken) add overflow checks to legacy RangeFrom tests will fail, but this is meant for checking how it affects compile times, which shouldn't be impacted by the broken logic --- library/core/src/iter/range.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 4fa719de5ebf0..b3bd78e5443d5 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1013,6 +1013,12 @@ impl Iterator for ops::RangeFrom { #[inline] fn next(&mut self) -> Option { + #[cfg(not(bootstrap))] + if crate::intrinsics::overflow_checks() { + self.start = Step::forward(self.start.clone(), 1); + return Some(self.start.clone()); + } + let n = Step::forward(self.start.clone(), 1); Some(mem::replace(&mut self.start, n)) } @@ -1024,6 +1030,13 @@ impl Iterator for ops::RangeFrom { #[inline] fn nth(&mut self, n: usize) -> Option { + #[cfg(not(bootstrap))] + if crate::intrinsics::overflow_checks() { + let plus_n = Step::forward(self.start.clone(), n); + self.start = Step::forward(plus_n.clone(), 1); + return Some(self.start.clone()); + } + let plus_n = Step::forward(self.start.clone(), n); self.start = Step::forward(plus_n.clone(), 1); Some(plus_n) From a7c9eb6b0488ca16629b4910203e5f378691b14b Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 3 May 2025 23:54:46 -0600 Subject: [PATCH 6/6] fmt --- compiler/rustc_const_eval/src/interpret/machine.rs | 10 ++++++++-- compiler/rustc_mir_transform/src/instsimplify.rs | 4 +++- library/core/src/iter/range.rs | 2 +- tests/codegen/iterrangefrom-overflow-checks.rs | 3 +-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index b848ef3838bd7..9b47dfbdf1d2f 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -297,7 +297,10 @@ pub trait Machine<'tcx>: Sized { } /// Determines the result of a `NullaryOp::RuntimeChecks` invocation. - fn runtime_checks(_ecx: &InterpCx<'tcx, Self>, r: mir::RuntimeChecks) -> InterpResult<'tcx, bool>; + fn runtime_checks( + _ecx: &InterpCx<'tcx, Self>, + r: mir::RuntimeChecks, + ) -> InterpResult<'tcx, bool>; /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction. /// You can use this to detect long or endlessly running programs. @@ -674,7 +677,10 @@ pub macro compile_time_machine(<$tcx: lifetime>) { } #[inline(always)] - fn runtime_checks(_ecx: &InterpCx<$tcx, Self>, _r: mir::RuntimeChecks) -> InterpResult<$tcx, bool> { + 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) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index b019ecf3e7322..efed9801ca86f 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -169,7 +169,9 @@ 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 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 }; diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index b3bd78e5443d5..f43f4d31bfa61 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1036,7 +1036,7 @@ impl Iterator for ops::RangeFrom { self.start = Step::forward(plus_n.clone(), 1); return Some(self.start.clone()); } - + let plus_n = Step::forward(self.start.clone(), n); self.start = Step::forward(plus_n.clone(), 1); Some(plus_n) diff --git a/tests/codegen/iterrangefrom-overflow-checks.rs b/tests/codegen/iterrangefrom-overflow-checks.rs index 14c0f41d958e5..e101968280f5d 100644 --- a/tests/codegen/iterrangefrom-overflow-checks.rs +++ b/tests/codegen/iterrangefrom-overflow-checks.rs @@ -11,9 +11,8 @@ //@ compile-flags: -O -Cdebug-assertions=yes #![crate_type = "lib"] - #![feature(new_range_api)] -use std::range::{RangeFrom, IterRangeFrom}; +use std::range::{IterRangeFrom, RangeFrom}; // CHECK-LABEL: @iterrangefrom_remainder( #[no_mangle]