From 9842a5ca7ff99916fe866f70833fb9dfd9031e23 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:23:52 -0500 Subject: [PATCH 01/10] Don't lower assume in unoptimized builds --- compiler/rustc_codegen_ssa/src/mir/statement.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index a158fc6e26074..ac7dfbb261dec 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,5 +1,6 @@ use rustc_middle::mir; use rustc_middle::mir::NonDivergingIntrinsic; +use rustc_session::config::OptLevel; use super::FunctionCx; use super::LocalRef; @@ -67,8 +68,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_coverage(bx, coverage, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { - let op_val = self.codegen_operand(bx, op); - bx.assume(op_val.immediate()); + if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) { + let op_val = self.codegen_operand(bx, op); + bx.assume(op_val.immediate()); + } } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( mir::CopyNonOverlapping { ref count, ref src, ref dst }, From 580067c76f0f5b8b356c202c8fce939325f63f29 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:24:23 -0500 Subject: [PATCH 02/10] InstSimplify rustc_nounwind calls --- .../rustc_mir_transform/src/instsimplify.rs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index a28db0defc993..f65eb5cbea938 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -2,10 +2,12 @@ use crate::simplify::simplify_duplicate_switch_targets; use rustc_middle::mir::*; +use rustc_middle::ty::layout; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt}; use rustc_span::symbol::Symbol; use rustc_target::abi::FieldIdx; +use rustc_target::spec::abi::Abi; pub struct InstSimplify; @@ -38,6 +40,7 @@ impl<'tcx> MirPass<'tcx> for InstSimplify { block.terminator.as_mut().unwrap(), &mut block.statements, ); + ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap()); simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); } } @@ -252,6 +255,28 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { terminator.kind = TerminatorKind::Goto { target: destination_block }; } + fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { + let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else { + return; + }; + + let Some((def_id, _)) = func.const_fn_def() else { + return; + }; + + let body_ty = self.tcx.type_of(def_id).skip_binder(); + let body_abi = match body_ty.kind() { + ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(), + ty::Closure(..) => Abi::RustCall, + ty::Coroutine(..) => Abi::Rust, + _ => bug!("unexpected body ty: {:?}", body_ty), + }; + + if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) { + *unwind = UnwindAction::Unreachable; + } + } + fn simplify_intrinsic_assert( &self, terminator: &mut Terminator<'tcx>, From 55fabf35b1069e071e46a153896d897829268db9 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:25:32 -0500 Subject: [PATCH 03/10] Add a new debug_assertions intrinsic --- library/core/src/intrinsics.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 6ea80c8d42faa..7ff9730254cb3 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2569,6 +2569,17 @@ extern "rust-intrinsic" { #[rustc_nounwind] #[cfg(not(bootstrap))] pub fn is_val_statically_known(arg: T) -> bool; + + #[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] + #[rustc_safe_intrinsic] + #[cfg(not(bootstrap))] + pub(crate) fn debug_assertions() -> bool; +} + +#[cfg(bootstrap)] +#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] +pub(crate) const fn debug_assertions() -> bool { + cfg!(debug_assertions) } // FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable` From 8836ac5758c1a470c73798eeae845556e7294f67 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:26:00 -0500 Subject: [PATCH 04/10] Add a new debug_assertions instrinsic (compiler) And in clippy --- compiler/rustc_borrowck/src/type_check/mod.rs | 1 + compiler/rustc_codegen_cranelift/src/base.rs | 9 +++++++++ compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 14 +++++++++---- .../rustc_const_eval/src/interpret/step.rs | 20 +++++++++++++++---- .../src/transform/check_consts/check.rs | 5 ++++- .../src/transform/validate.rs | 2 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 5 ++++- compiler/rustc_middle/src/mir/pretty.rs | 1 + compiler/rustc_middle/src/mir/syntax.rs | 2 ++ compiler/rustc_middle/src/mir/tcx.rs | 1 + .../src/move_paths/builder.rs | 5 ++++- .../src/const_prop_lint.rs | 1 + compiler/rustc_mir_transform/src/gvn.rs | 1 + .../src/lower_intrinsics.rs | 11 ++++++++++ .../rustc_mir_transform/src/promote_consts.rs | 1 + .../rustc_smir/src/rustc_smir/convert/mir.rs | 1 + compiler/stable_mir/src/mir/body.rs | 3 +++ .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- 18 files changed, 72 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index fd20d35220306..1c883f4c62145 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1984,6 +1984,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::SizedBound, ); } + &Rvalue::NullaryOp(NullOp::DebugAssertions, _) => {} Rvalue::ShallowInitBox(operand, ty) => { self.check_operand(operand, location); diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 0afd6d0e670b3..a7e76fbc128ea 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -767,6 +767,15 @@ fn codegen_stmt<'tcx>( NullOp::OffsetOf(fields) => { layout.offset_of_subfield(fx, fields.iter()).bytes() } + NullOp::DebugAssertions => { + let val = fx.tcx.sess.opts.debug_assertions; + let val = CValue::by_val( + fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()), + fx.layout_of(fx.tcx.types.bool), + ); + lval.write_cvalue(fx, val); + return; + } }; let val = CValue::by_val( fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()), diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 266505d3f2691..5c6060a7159aa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -672,17 +672,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = match null_op { mir::NullOp::SizeOf => { assert!(bx.cx().type_is_sized(ty)); - layout.size.bytes() + let val = layout.size.bytes(); + bx.cx().const_usize(val) } mir::NullOp::AlignOf => { assert!(bx.cx().type_is_sized(ty)); - layout.align.abi.bytes() + let val = layout.align.abi.bytes(); + bx.cx().const_usize(val) } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(bx.cx(), fields.iter()).bytes() + let val = layout.offset_of_subfield(bx.cx(), fields.iter()).bytes(); + bx.cx().const_usize(val) + } + mir::NullOp::DebugAssertions => { + let val = bx.tcx().sess.opts.debug_assertions; + bx.cx().const_bool(val) } }; - let val = bx.cx().const_usize(val); let tcx = self.cx.tcx(); OperandRef { val: OperandValue::Immediate(val), diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index d48329b6c6946..f0f1008aba80b 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -246,13 +246,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); } let val = match null_op { - mir::NullOp::SizeOf => layout.size.bytes(), - mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::SizeOf => { + let val = layout.size.bytes(); + Scalar::from_target_usize(val, self) + } + mir::NullOp::AlignOf => { + let val = layout.align.abi.bytes(); + Scalar::from_target_usize(val, self) + } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(self, fields.iter()).bytes() + let val = layout.offset_of_subfield(self, fields.iter()).bytes(); + Scalar::from_target_usize(val, self) + } + mir::NullOp::DebugAssertions => { + // The checks hidden behind this are always better done by the interpreter + // itself, because it knows the runtime state better. + Scalar::from_bool(false) } }; - self.write_scalar(Scalar::from_target_usize(val, self), &dest)?; + self.write_scalar(val, &dest)?; } ShallowInitBox(ref operand, _) => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 5ff81615552bf..ee3f349c6b83c 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -544,7 +544,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Cast(_, _, _) => {} - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {} + Rvalue::NullaryOp( + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, + _, + ) => {} Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, operand) => { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index c4542aaa7b2fb..db4d2be5470e1 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -1139,7 +1139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) | Rvalue::AddressOf(_, _) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::DebugAssertions, _) | Rvalue::Discriminant(_) => {} } self.super_rvalue(rvalue, location); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 2d0d6611444c5..96b0cffc8a3d4 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -112,7 +112,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir | sym::forget | sym::black_box | sym::variant_count - | sym::ptr_mask => hir::Unsafety::Normal, + | sym::ptr_mask + | sym::debug_assertions => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, }; @@ -461,6 +462,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize) } + sym::debug_assertions => (0, Vec::new(), tcx.types.bool), + other => { tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other }); return; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 6f587fdd53c61..b601b465668e9 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -907,6 +907,7 @@ 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::DebugAssertions => write!(fmt, "cfg!(debug_assertions)"), } } 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 ca56e1fd92c6b..40af453f6ce6f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1361,6 +1361,8 @@ pub enum NullOp<'tcx> { AlignOf, /// Returns the offset of a field OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>), + /// cfg!(debug_assertions), but expanded in codegen + DebugAssertions, } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 4780042a51090..5bc151de659c3 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -194,6 +194,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { tcx.types.usize } + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => 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 => { diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 30dd915521cd2..80e0d0baf5786 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -429,7 +429,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {} + | Rvalue::NullaryOp( + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::DebugAssertions, + _, + ) => {} } } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index f2448ee3d44af..4dccc01d041f8 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -639,6 +639,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { NullOp::OffsetOf(fields) => { op_layout.offset_of_subfield(self, fields.iter()).bytes() } + NullOp::DebugAssertions => return None, }; ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into() } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 6e4f8f710b683..36c441a394536 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -489,6 +489,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { NullOp::OffsetOf(fields) => { layout.offset_of_subfield(&self.ecx, fields.iter()).bytes() } + NullOp::DebugAssertions => return None, }; let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); let imm = ImmTy::try_from_uint(val, usize_layout)?; diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 897375e0e1645..f43b85173d428 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -21,6 +21,17 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { sym::unreachable => { terminator.kind = TerminatorKind::Unreachable; } + sym::debug_assertions => { + let target = target.unwrap(); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::NullaryOp(NullOp::DebugAssertions, tcx.types.bool), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; + } sym::forget => { if let Some(target) = *target { block.statements.push(Statement { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index c00093ea27edd..577b8f2080fcd 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -446,6 +446,7 @@ impl<'tcx> Validator<'_, 'tcx> { NullOp::SizeOf => {} NullOp::AlignOf => {} NullOp::OffsetOf(_) => {} + NullOp::DebugAssertions => {} }, Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 41a4edfc03b58..501d6f7d304ef 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -257,6 +257,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf( indices.iter().map(|idx| idx.stable(tables)).collect(), ), + DebugAssertions => stable_mir::mir::NullOp::DebugAssertions, } } } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 38877f7a77fc4..be727f024c609 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -639,6 +639,7 @@ impl Rvalue { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { Ok(Ty::usize_ty()) } + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => 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( @@ -1005,6 +1006,8 @@ pub enum NullOp { AlignOf, /// Returns the offset of a field. OffsetOf(Vec<(VariantIdx, FieldIdx)>), + /// cfg!(debug_assertions), but at codegen time + DebugAssertions, } impl Operand { 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 81f4fcc2133d1..8d5bcd665ad25 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 @@ -174,7 +174,7 @@ fn check_rvalue<'tcx>( )) } }, - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) | Rvalue::ShallowInitBox(_, _) => { + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, _) | Rvalue::ShallowInitBox(_, _) => { Ok(()) }, Rvalue::UnaryOp(_, operand) => { From 61118ffd04aa6d1f9ee92daae4deb28bd975d4ab Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:27:57 -0500 Subject: [PATCH 05/10] Rewrite assert_unsafe_precondition around the new intrinsic --- library/core/src/char/convert.rs | 2 +- library/core/src/hint.rs | 2 +- library/core/src/intrinsics.rs | 123 +++++++++++++++++++++--------- library/core/src/ptr/const_ptr.rs | 8 +- library/core/src/ptr/mod.rs | 45 ++++++++--- library/core/src/ptr/non_null.rs | 5 +- library/core/src/slice/raw.rs | 21 ++++- 7 files changed, 147 insertions(+), 59 deletions(-) diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 177f39b59aed7..7bd592492a5c3 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -27,7 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char { unsafe { assert_unsafe_precondition!( "invalid value for `char`", - (i: u32) => char_try_from_u32(i).is_ok() + (i: u32 = i) => char_try_from_u32(i).is_ok() ); transmute(i) } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 5c44ca69451dd..97c3c9e6fae95 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -148,7 +148,7 @@ pub const unsafe fn assert_unchecked(cond: bool) { unsafe { intrinsics::assert_unsafe_precondition!( "hint::assert_unchecked must never be called when the condition is false", - (cond: bool) => cond, + (cond: bool = cond) => cond, ); crate::intrinsics::assume(cond); } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 7ff9730254cb3..a6311e416333b 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -56,7 +56,7 @@ use crate::marker::DiscriminantKind; use crate::marker::Tuple; -use crate::mem; +use crate::mem::{self, align_of}; pub mod mir; pub mod simd; @@ -2598,10 +2598,27 @@ pub const unsafe fn is_val_statically_known(_arg: T) -> bool { /// Check that the preconditions of an unsafe function are followed, if debug_assertions are on, /// and only at runtime. /// -/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)` -/// where the names specified will be moved into the macro as captured variables, and defines an item -/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics -/// for the function declarations and can be omitted if there is no generics. +/// This macro should be called as +/// `assert_unsafe_precondition!((expr => name: Type, expr => name: Type) => Expression)` +/// where each `expr` will be evaluated and passed in as function argument `name: Type`. Then all +/// those arguments are passed to a function via [`const_eval_select`]. +/// +/// These checks are behind a condition which is evaluated at codegen time, not expansion time like +/// [`debug_assert`]. This means that a standard library built with optimizations and debug +/// assertions disabled will have these checks optimized out of its monomorphizations, but if a +/// a caller of the standard library has debug assertions enabled and monomorphizes an expansion of +/// this macro, that monomorphization will contain the check. +/// +/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and +/// implementation to mitigate their compile-time overhead. The runtime function that we +/// [`const_eval_select`] to is monomorphic, `#[inline(never)]`, and `#[rustc_nounwind]`. That +/// combination of properties ensures that the code for the checks is only compiled once, and has a +/// minimal impact on the caller's code size. +/// +/// Caller should also introducing any other `let` bindings or any code outside this macro in order +/// to call it. Since the precompiled standard library is built with full debuginfo and these +/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough +/// debuginfo to have a measurable compile-time impact on debug builds. /// /// # Safety /// @@ -2615,26 +2632,24 @@ pub const unsafe fn is_val_statically_known(_arg: T) -> bool { /// /// So in a sense it is UB if this macro is useful, but we expect callers of `unsafe fn` to make /// the occasional mistake, and this check should help them figure things out. -#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn +#[allow_internal_unstable(const_eval_select, delayed_debug_assertions)] // permit this to be called in stably-const fn macro_rules! assert_unsafe_precondition { - ($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => { - if cfg!(debug_assertions) { - // allow non_snake_case to allow capturing const generics - #[allow(non_snake_case)] - #[inline(always)] - fn runtime$(<$($tt)*>)?($($i:$ty),*) { + ($message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => { + { + #[inline(never)] + #[rustc_nounwind] + fn precondition_check($($name:$ty),*) { if !$e { - // don't unwind to reduce impact on code size ::core::panicking::panic_nounwind( - concat!("unsafe precondition(s) violated: ", $name) + concat!("unsafe precondition(s) violated: ", $message) ); } } - #[allow(non_snake_case)] - #[inline] - const fn comptime$(<$($tt)*>)?($(_:$ty),*) {} + const fn comptime($(_:$ty),*) {} - ::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime); + if ::core::intrinsics::debug_assertions() { + ::core::intrinsics::const_eval_select(($($arg,)*), comptime, precondition_check); + } } }; } @@ -2643,30 +2658,47 @@ pub(crate) use assert_unsafe_precondition; /// Checks whether `ptr` is properly aligned with respect to /// `align_of::()`. #[inline] -pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { - !ptr.is_null() && ptr.is_aligned() +pub(crate) fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool { + !ptr.is_null() && ptr.is_aligned_to(align) } -/// Checks whether an allocation of `len` instances of `T` exceeds -/// the maximum allowed allocation size. #[inline] -pub(crate) fn is_valid_allocation_size(len: usize) -> bool { - let max_len = const { - let size = crate::mem::size_of::(); - if size == 0 { usize::MAX } else { isize::MAX as usize / size } - }; +pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool { + let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size }; len <= max_len } +pub(crate) fn is_nonoverlapping_mono( + src: *const (), + dst: *const (), + size: usize, + count: usize, +) -> bool { + let src_usize = src.addr(); + let dst_usize = dst.addr(); + let Some(size) = size.checked_mul(count) else { + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::() * count` overflows a usize", + ) + }; + let diff = src_usize.abs_diff(dst_usize); + // If the absolute distance between the ptrs is at least as big as the size of the buffer, + // they do not overlap. + diff >= size +} + /// Checks whether the regions of memory starting at `src` and `dst` of size /// `count * size_of::()` do *not* overlap. #[inline] pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { let src_usize = src.addr(); let dst_usize = dst.addr(); - let size = mem::size_of::() - .checked_mul(count) - .expect("is_nonoverlapping: `size_of::() * count` overflows a usize"); + let Some(size) = mem::size_of::().checked_mul(count) else { + // Use panic_nounwind instead of Option::expect, so that this function is nounwind. + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::() * count` overflows a usize", + ) + }; let diff = src_usize.abs_diff(dst_usize); // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. @@ -2777,10 +2809,16 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us assert_unsafe_precondition!( "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ and the specified memory ranges do not overlap", - [T](src: *const T, dst: *mut T, count: usize) => - is_aligned_and_not_null(src) - && is_aligned_and_not_null(dst) - && is_nonoverlapping(src, dst, count) + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + count: usize = count, + ) => + is_aligned_and_not_null(src, align) + && is_aligned_and_not_null(dst, align) + && is_nonoverlapping_mono(src, dst, size, count) ); copy_nonoverlapping(src, dst, count) } @@ -2870,9 +2908,15 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { assert_unsafe_precondition!( - "ptr::copy requires that both pointer arguments are aligned and non-null", - [T](src: *const T, dst: *mut T) => - is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) + "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ + and the specified memory ranges do not overlap", + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => + is_aligned_and_not_null(src, align) + && is_aligned_and_not_null(dst, align) ); copy(src, dst, count) } @@ -2945,7 +2989,10 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { unsafe { assert_unsafe_precondition!( "ptr::write_bytes requires that the destination pointer is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *const () = dst as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); write_bytes(dst, val, count) } diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 1d5d683fa16cc..c5e3df07a1cf7 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -806,13 +806,15 @@ impl *const T { where T: Sized, { - let this = self; // SAFETY: The comparison has no side-effects, and the intrinsic // does this check internally in the CTFE implementation. unsafe { assert_unsafe_precondition!( - "ptr::sub_ptr requires `this >= origin`", - [T](this: *const T, origin: *const T) => this >= origin + "ptr::sub_ptr requires `self >= origin`", + ( + this: *const () = self as *const (), + origin: *const () = origin as *const (), + ) => this >= origin ) }; diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index bc05b5b07def3..0fb9017e6d941 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -381,11 +381,11 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash; use crate::intrinsics::{ - self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping, + self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping_mono, }; use crate::marker::FnPtr; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, align_of, size_of, MaybeUninit}; mod alignment; #[unstable(feature = "ptr_alignment_type", issue = "102070")] @@ -967,10 +967,16 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { assert_unsafe_precondition!( "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \ and the specified memory ranges do not overlap", - [T](x: *mut T, y: *mut T, count: usize) => - is_aligned_and_not_null(x) - && is_aligned_and_not_null(y) - && is_nonoverlapping(x, y, count) + ( + x: *mut () = x as *mut (), + y: *mut () = y as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + count: usize = count, + ) => + is_aligned_and_not_null(x, align) + && is_aligned_and_not_null(y, align) + && is_nonoverlapping_mono(x, y, size, count) ); } @@ -1061,7 +1067,10 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { unsafe { assert_unsafe_precondition!( "ptr::replace requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *const () = dst as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); mem::swap(&mut *dst, &mut src); // cannot overlap } @@ -1207,9 +1216,13 @@ pub const unsafe fn read(src: *const T) -> T { // SAFETY: the caller must guarantee that `src` is valid for reads. unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) assert_unsafe_precondition!( "ptr::read requires that the pointer argument is aligned and non-null", - [T](src: *const T) => is_aligned_and_not_null(src) + ( + addr: *const () = src as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); crate::intrinsics::read_via_copy(src) } @@ -1411,9 +1424,13 @@ pub const unsafe fn write(dst: *mut T, src: T) { // `dst` cannot overlap `src` because the caller has mutable access // to `dst` while `src` is owned by this function. unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) assert_unsafe_precondition!( "ptr::write requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::write_via_move(dst, src) } @@ -1581,7 +1598,10 @@ pub unsafe fn read_volatile(src: *const T) -> T { unsafe { assert_unsafe_precondition!( "ptr::read_volatile requires that the pointer argument is aligned and non-null", - [T](src: *const T) => is_aligned_and_not_null(src) + ( + addr: *const () = src as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::volatile_load(src) } @@ -1656,7 +1676,10 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { unsafe { assert_unsafe_precondition!( "ptr::write_volatile requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::volatile_store(dst, src); } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d18082c3048f1..d6266ba8da52e 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -218,7 +218,10 @@ impl NonNull { pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: the caller must guarantee that `ptr` is non-null. unsafe { - assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null()); + assert_unsafe_precondition!( + "NonNull::new_unchecked requires that the pointer is non-null", + (ptr: *mut () = ptr as *mut ()) => !ptr.is_null() + ); NonNull { pointer: ptr as _ } } } diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 9cdf9b68afb72..571abc3e99907 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -4,6 +4,7 @@ use crate::array; use crate::intrinsics::{ assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size, }; +use crate::mem::{align_of, size_of}; use crate::ops::Range; use crate::ptr; @@ -96,8 +97,14 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] unsafe { assert_unsafe_precondition!( "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", - [T](data: *const T, len: usize) => is_aligned_and_not_null(data) - && is_valid_allocation_size::(len) + ( + data: *mut () = data as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + len: usize = len, + ) => + is_aligned_and_not_null(data, align) + && is_valid_allocation_size(size, len) ); &*ptr::slice_from_raw_parts(data, len) } @@ -143,8 +150,14 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m unsafe { assert_unsafe_precondition!( "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", - [T](data: *mut T, len: usize) => is_aligned_and_not_null(data) - && is_valid_allocation_size::(len) + ( + data: *mut () = data as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + len: usize = len, + ) => + is_aligned_and_not_null(data, align) + && is_valid_allocation_size(size, len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) } From b0ea682a2cad2c49595c95dcb7e7608d090484f1 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:29:07 -0500 Subject: [PATCH 06/10] Remove a now-obviated debug_assert! --- library/core/src/option.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c94e7d73a2ae6..ab005228984e0 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1033,7 +1033,6 @@ impl Option { #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] pub const unsafe fn unwrap_unchecked(self) -> T { - debug_assert!(self.is_some()); match self { Some(val) => val, // SAFETY: the safety contract must be upheld by the caller. From 88d6e9f868d7bd21aa2b6c641f8743fe7e53e67b Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:29:33 -0500 Subject: [PATCH 07/10] Reduce use of NonNull::new_unchecked in library/ --- library/alloc/src/raw_vec.rs | 13 +++++++------ library/alloc/src/vec/into_iter.rs | 2 +- library/alloc/src/vec/mod.rs | 6 +++--- library/core/src/ptr/non_null.rs | 10 ++++------ library/core/src/ptr/unique.rs | 2 +- library/core/src/slice/iter.rs | 15 ++++++++------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 94e6924f41a75..49f5f53f9b30a 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -207,11 +207,7 @@ impl RawVec { // Allocators currently return a `NonNull<[u8]>` whose length // matches the size requested. If that ever changes, the capacity // here should change to `ptr.len() / mem::size_of::()`. - Self { - ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, - cap: unsafe { Cap(capacity) }, - alloc, - } + Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc } } } @@ -239,6 +235,11 @@ impl RawVec { self.ptr.as_ptr() } + #[inline] + pub fn non_null(&self) -> NonNull { + NonNull::from(self.ptr) + } + /// Gets the capacity of the allocation. /// /// This will always be `usize::MAX` if `T` is zero-sized. @@ -398,7 +399,7 @@ impl RawVec { // Allocators currently return a `NonNull<[u8]>` whose length matches // the size requested. If that ever changes, the capacity here should // change to `ptr.len() / mem::size_of::()`. - self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }; + self.ptr = Unique::from(ptr.cast()); self.cap = unsafe { Cap(cap) }; } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 654ce09afcd30..7800560da94f9 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -136,7 +136,7 @@ impl IntoIter { // struct and then overwriting &mut self. // this creates less assembly self.cap = 0; - self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; + self.buf = RawVec::NEW.non_null(); self.ptr = self.buf; self.end = self.buf.as_ptr(); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b3e5ecc924071..08e3cdedc666b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2861,16 +2861,16 @@ impl IntoIterator for Vec { #[inline] fn into_iter(self) -> Self::IntoIter { unsafe { - let mut me = ManuallyDrop::new(self); + let me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); - let begin = me.as_mut_ptr(); + let buf = me.buf.non_null(); + let begin = buf.as_ptr(); let end = if T::IS_ZST { begin.wrapping_byte_add(me.len()) } else { begin.add(me.len()) as *const T }; let cap = me.buf.capacity(); - let buf = NonNull::new_unchecked(begin); IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end } } } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d6266ba8da52e..575af96fc982f 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -473,7 +473,7 @@ impl NonNull { #[inline] pub const fn cast(self) -> NonNull { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null - unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } + unsafe { NonNull { pointer: self.as_ptr() as *mut U } } } /// Calculates the offset from a pointer. @@ -1828,9 +1828,8 @@ impl hash::Hash for NonNull { impl From> for NonNull { #[inline] fn from(unique: Unique) -> Self { - // SAFETY: A Unique pointer cannot be null, so the conditions for - // new_unchecked() are respected. - unsafe { NonNull::new_unchecked(unique.as_ptr()) } + // SAFETY: A Unique pointer cannot be null. + unsafe { NonNull { pointer: unique.as_ptr() } } } } @@ -1853,8 +1852,7 @@ impl From<&T> for NonNull { /// This conversion is safe and infallible since references cannot be null. #[inline] fn from(reference: &T) -> Self { - // SAFETY: A reference cannot be null, so the conditions for - // new_unchecked() are respected. + // SAFETY: A reference cannot be null. unsafe { NonNull { pointer: reference as *const T } } } } diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 067f1541e31ae..2d878836b1627 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -138,7 +138,7 @@ impl Unique { pub const fn cast(self) -> Unique { // FIXME(const-hack): replace with `From` // SAFETY: is `NonNull` - unsafe { Unique::new_unchecked(self.pointer.cast().as_ptr()) } + Unique { pointer: self.pointer.cast(), _marker: PhantomData } } } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 2d4c7e78aea17..1ca4ecbfba9e9 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -87,12 +87,13 @@ unsafe impl Send for Iter<'_, T> {} impl<'a, T> Iter<'a, T> { #[inline] pub(super) fn new(slice: &'a [T]) -> Self { - let ptr = slice.as_ptr(); + let len = slice.len(); + let ptr: NonNull = NonNull::from(slice).cast(); // SAFETY: Similar to `IterMut::new`. unsafe { - let end_or_len = if T::IS_ZST { invalid(slice.len()) } else { ptr.add(slice.len()) }; + let end_or_len = if T::IS_ZST { invalid(len) } else { ptr.as_ptr().add(len) }; - Self { ptr: NonNull::new_unchecked(ptr as *mut T), end_or_len, _marker: PhantomData } + Self { ptr, end_or_len, _marker: PhantomData } } } @@ -208,7 +209,8 @@ unsafe impl Send for IterMut<'_, T> {} impl<'a, T> IterMut<'a, T> { #[inline] pub(super) fn new(slice: &'a mut [T]) -> Self { - let ptr = slice.as_mut_ptr(); + let len = slice.len(); + let ptr: NonNull = NonNull::from(slice).cast(); // SAFETY: There are several things here: // // `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid @@ -226,10 +228,9 @@ impl<'a, T> IterMut<'a, T> { // See the `next_unchecked!` and `is_empty!` macros as well as the // `post_inc_start` method for more information. unsafe { - let end_or_len = - if T::IS_ZST { invalid_mut(slice.len()) } else { ptr.add(slice.len()) }; + let end_or_len = if T::IS_ZST { invalid_mut(len) } else { ptr.as_ptr().add(len) }; - Self { ptr: NonNull::new_unchecked(ptr), end_or_len, _marker: PhantomData } + Self { ptr, end_or_len, _marker: PhantomData } } } From 9e1b2d909bec461d334b412bdbc0d0f8ba6c17ed Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:30:11 -0500 Subject: [PATCH 08/10] Add new ui tests --- src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/precondition-checks/misaligned-slice.rs | 11 +++++++++++ tests/ui/precondition-checks/null-slice.rs | 11 +++++++++++ .../out-of-bounds-get-unchecked.rs | 12 ++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests/ui/precondition-checks/misaligned-slice.rs create mode 100644 tests/ui/precondition-checks/null-slice.rs create mode 100644 tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 4a44c40debd22..d5df05bacd93f 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1819; -const ROOT_ENTRY_LIMIT: usize = 871; +const ROOT_ENTRY_LIMIT: usize = 872; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/precondition-checks/misaligned-slice.rs b/tests/ui/precondition-checks/misaligned-slice.rs new file mode 100644 index 0000000000000..c961c80035232 --- /dev/null +++ b/tests/ui/precondition-checks/misaligned-slice.rs @@ -0,0 +1,11 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let _s: &[u64] = std::slice::from_raw_parts(1usize as *const u64, 0); + } +} diff --git a/tests/ui/precondition-checks/null-slice.rs b/tests/ui/precondition-checks/null-slice.rs new file mode 100644 index 0000000000000..1e67e7f5fb1d0 --- /dev/null +++ b/tests/ui/precondition-checks/null-slice.rs @@ -0,0 +1,11 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0); + } +} diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs new file mode 100644 index 0000000000000..1366ba28f1c9e --- /dev/null +++ b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs @@ -0,0 +1,12 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: hint::assert_unchecked +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let sli: &[u8] = &[0]; + sli.get_unchecked(1); + } +} From 611c3cb56109593824f3570720d8404b591724cc Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:30:39 -0500 Subject: [PATCH 09/10] Bless/fix tests --- tests/assembly/is_aligned.rs | 4 +- ...n.DataflowConstProp.32bit.panic-abort.diff | 60 ++--- ....DataflowConstProp.32bit.panic-unwind.diff | 68 +++-- ...n.DataflowConstProp.64bit.panic-abort.diff | 60 ++--- ....DataflowConstProp.64bit.panic-unwind.diff | 68 +++-- ...oxed_slice.main.GVN.32bit.panic-abort.diff | 63 +++-- ...xed_slice.main.GVN.32bit.panic-unwind.diff | 71 +++-- ...oxed_slice.main.GVN.64bit.panic-abort.diff | 63 +++-- ...xed_slice.main.GVN.64bit.panic-unwind.diff | 71 +++-- tests/mir-opt/inline/unwrap_unchecked.rs | 2 +- ...d.unwrap_unchecked.Inline.panic-abort.diff | 39 +-- ....unwrap_unchecked.Inline.panic-unwind.diff | 51 ++-- ...unchecked.PreCodegen.after.panic-abort.mir | 34 +-- ...nchecked.PreCodegen.after.panic-unwind.mir | 34 +-- ...witch_targets.ub_if_b.PreCodegen.after.mir | 22 +- ..._replace.PreCodegen.after.panic-abort.mir} | 0 ..._replace.PreCodegen.after.panic-unwind.mir | 16 ++ ...m_replace.mem_replace.PreCodegen.after.mir | 66 ----- ...m_replace.PreCodegen.after.panic-abort.mir | 33 +++ ..._replace.PreCodegen.after.panic-unwind.mir | 33 +++ tests/mir-opt/pre-codegen/mem_replace.rs | 3 +- ...ated_loop.PreCodegen.after.panic-abort.mir | 240 +++++++++-------- ...ted_loop.PreCodegen.after.panic-unwind.mir | 240 +++++++++-------- ...ward_loop.PreCodegen.after.panic-abort.mir | 216 ++++++++-------- ...ard_loop.PreCodegen.after.panic-unwind.mir | 216 ++++++++-------- ...erse_loop.PreCodegen.after.panic-abort.mir | 244 +++++++++--------- ...rse_loop.PreCodegen.after.panic-unwind.mir | 244 +++++++++--------- tests/ui/hygiene/panic-location.run.stderr | 2 +- 28 files changed, 1113 insertions(+), 1150 deletions(-) rename tests/mir-opt/pre-codegen/{mem_replace.manual_replace.PreCodegen.after.mir => mem_replace.manual_replace.PreCodegen.after.panic-abort.mir} (100%) create mode 100644 tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir delete mode 100644 tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir create mode 100644 tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir create mode 100644 tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir diff --git a/tests/assembly/is_aligned.rs b/tests/assembly/is_aligned.rs index d152d200adfd7..c4a7823ce1ad4 100644 --- a/tests/assembly/is_aligned.rs +++ b/tests/assembly/is_aligned.rs @@ -2,8 +2,8 @@ // only-x86_64 // ignore-sgx // revisions: opt-speed opt-size -// [opt-speed] compile-flags: -Copt-level=1 -// [opt-size] compile-flags: -Copt-level=s +// [opt-speed] compile-flags: -Copt-level=2 -Cdebug-assertions=no +// [opt-size] compile-flags: -Copt-level=s -Cdebug-assertions=no #![crate_type="rlib"] #![feature(core_intrinsics)] diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index ffbd97bb5452f..94cfb4e63fc22 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,30 +56,41 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 7b6dcf1972b2e..ee85287882be9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,34 +56,45 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index ffbd97bb5452f..94cfb4e63fc22 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,30 +56,41 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 7b6dcf1972b2e..ee85287882be9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,34 +56,45 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index df68ce496fd8c..4df38d6e61b7e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,31 +58,43 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index e16ea22091ee2..6aac30bcd17fb 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,35 +58,47 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index df68ce496fd8c..4df38d6e61b7e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,31 +58,43 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index e16ea22091ee2..6aac30bcd17fb 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,35 +58,47 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.rs b/tests/mir-opt/inline/unwrap_unchecked.rs index be133706e5c22..1adf2224d976a 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.rs +++ b/tests/mir-opt/inline/unwrap_unchecked.rs @@ -2,7 +2,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // ignore-debug: the debug assertions prevent the inlining we are testing for -// compile-flags: -Zmir-opt-level=2 -Zinline-mir +// compile-flags: -Zmir-opt-level=2 -Zinline-mir -Cdebug-assertions=no // EMIT_MIR unwrap_unchecked.unwrap_unchecked.Inline.diff // EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir 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 2a36ad9230e4b..9358a64b4fabe 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 @@ -7,41 +7,44 @@ let mut _2: std::option::Option; + scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { + debug self => _2; -+ let mut _3: &std::option::Option; -+ let mut _4: isize; -+ let mut _5: bool; ++ let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 { -+ scope 5 (inlined unreachable_unchecked) { -+ scope 6 { -+ scope 7 (inlined unreachable_unchecked::runtime) { -+ } ++ scope 4 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 5 { + } + } + } -+ scope 4 (inlined Option::::is_some) { -+ debug self => _3; -+ } + } bb0: { StorageLive(_2); _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable]; -- } -- -- bb1: { + StorageLive(_3); -+ StorageLive(_4); + StorageLive(_5); -+ _4 = discriminant(_2); -+ _5 = Eq(_4, const 1_isize); -+ assume(move _5); ++ _3 = discriminant(_2); ++ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { ++ StorageLive(_4); ++ _4 = cfg!(debug_assertions); ++ assume(_4); ++ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; ++ } ++ ++ bb2: { ++ unreachable; ++ } ++ ++ bb3: { + _0 = move ((_2 as Some).0: T); + StorageDead(_5); -+ StorageDead(_4); + StorageDead(_3); StorageDead(_2); return; 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 14c8c671d3fe2..ac33c126155ca 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 @@ -7,48 +7,51 @@ let mut _2: std::option::Option; + scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { + debug self => _2; -+ let mut _3: &std::option::Option; -+ let mut _4: isize; -+ let mut _5: bool; ++ let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 { -+ scope 5 (inlined unreachable_unchecked) { -+ scope 6 { -+ scope 7 (inlined unreachable_unchecked::runtime) { -+ } ++ scope 4 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 5 { + } + } + } -+ scope 4 (inlined Option::::is_some) { -+ debug self => _3; -+ } + } bb0: { StorageLive(_2); _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2]; -- } -- -- bb1: { + StorageLive(_3); -+ StorageLive(_4); + StorageLive(_5); -+ _4 = discriminant(_2); -+ _5 = Eq(_4, const 1_isize); -+ assume(move _5); ++ _3 = discriminant(_2); ++ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { +- StorageDead(_2); +- return; ++ StorageLive(_4); ++ _4 = cfg!(debug_assertions); ++ assume(_4); ++ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; + } + +- bb2 (cleanup): { +- resume; ++ bb2: { ++ unreachable; ++ } ++ ++ bb3: { + _0 = move ((_2 as Some).0: T); + StorageDead(_5); -+ StorageDead(_4); + StorageDead(_3); - StorageDead(_2); - return; -- } -- -- bb2 (cleanup): { -- resume; ++ StorageDead(_2); ++ return; } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index d6a608476df9c..8ec65935c6612 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option) -> T { scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { debug self => _1; let mut _2: isize; - let mut _3: bool; - let mut _4: &std::option::Option; scope 2 { debug val => _0; } scope 3 { - scope 5 (inlined unreachable_unchecked) { - scope 6 { - scope 7 (inlined unreachable_unchecked::runtime) { - } + scope 4 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); + scope 5 { } } } - scope 4 (inlined Option::::is_some) { - debug self => _4; - } } bb0: { - StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); - _3 = Eq(_2, const 1_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb2: { _0 = ((_1 as Some).0: T); - StorageDead(_3); StorageDead(_2); - StorageDead(_4); return; } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index d6a608476df9c..8ec65935c6612 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option) -> T { scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { debug self => _1; let mut _2: isize; - let mut _3: bool; - let mut _4: &std::option::Option; scope 2 { debug val => _0; } scope 3 { - scope 5 (inlined unreachable_unchecked) { - scope 6 { - scope 7 (inlined unreachable_unchecked::runtime) { - } + scope 4 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); + scope 5 { } } } - scope 4 (inlined Option::::is_some) { - debug self => _4; - } } bb0: { - StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); - _3 = Eq(_2, const 1_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb2: { _0 = ((_1 as Some).0: T); - StorageDead(_3); StorageDead(_2); - StorageDead(_4); return; } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir index 0114309dbb58e..7c038b0ee88e7 100644 --- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir @@ -4,19 +4,31 @@ fn ub_if_b(_1: Thing) -> Thing { debug t => _1; let mut _0: Thing; let mut _2: isize; - let mut _3: bool; scope 1 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); scope 2 { - scope 3 (inlined unreachable_unchecked::runtime) { - } } } bb0: { _2 = discriminant(_1); - _3 = Eq(_2, const 0_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { _0 = move _1; return; } + + bb2: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir similarity index 100% rename from tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir rename to tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..3ca24e152a4e0 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,16 @@ +// MIR for `manual_replace` after PreCodegen + +fn manual_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 { + debug temp => _0; + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir deleted file mode 100644 index f0cb4ca31fecc..0000000000000 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir +++ /dev/null @@ -1,66 +0,0 @@ -// MIR for `mem_replace` after PreCodegen - -fn mem_replace(_1: &mut u32, _2: u32) -> u32 { - debug r => _1; - debug v => _2; - let mut _0: u32; - scope 1 (inlined std::mem::replace::) { - debug dest => _1; - debug src => _2; - scope 2 { - scope 3 { - debug result => _0; - scope 16 (inlined std::ptr::write::) { - debug dst => _1; - debug src => _2; - scope 17 { - } - } - } - scope 4 (inlined std::ptr::read::) { - debug src => _1; - let mut _3: *const u32; - scope 5 { - scope 6 (inlined std::ptr::read::runtime::) { - debug src => _3; - scope 7 (inlined intrinsics::is_aligned_and_not_null::) { - debug ptr => _3; - scope 8 (inlined std::ptr::const_ptr::::is_null) { - debug self => _3; - let mut _4: *const u8; - scope 9 { - scope 10 (inlined std::ptr::const_ptr::::is_null::runtime_impl) { - debug ptr => _4; - scope 11 (inlined std::ptr::const_ptr::::addr) { - debug self => _4; - scope 12 { - scope 13 (inlined std::ptr::const_ptr::::cast::<()>) { - debug self => _4; - } - } - } - } - } - } - scope 14 (inlined std::ptr::const_ptr::::is_aligned) { - debug self => _3; - scope 15 (inlined align_of::) { - } - } - } - } - } - } - } - } - - bb0: { - StorageLive(_3); - StorageLive(_4); - _0 = (*_1); - StorageDead(_4); - StorageDead(_3); - (*_1) = _2; - return; - } -} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir new file mode 100644 index 0000000000000..26919dd98dd27 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir @@ -0,0 +1,33 @@ +// MIR for `mem_replace` after PreCodegen + +fn mem_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 (inlined std::mem::replace::) { + debug dest => _1; + debug src => _2; + scope 2 { + scope 3 { + debug result => _0; + scope 6 (inlined std::ptr::write::) { + debug dst => _1; + debug src => _2; + scope 7 { + } + } + } + scope 4 (inlined std::ptr::read::) { + debug src => _1; + scope 5 { + } + } + } + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..26919dd98dd27 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,33 @@ +// MIR for `mem_replace` after PreCodegen + +fn mem_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 (inlined std::mem::replace::) { + debug dest => _1; + debug src => _2; + scope 2 { + scope 3 { + debug result => _0; + scope 6 (inlined std::ptr::write::) { + debug dst => _1; + debug src => _2; + scope 7 { + } + } + } + scope 4 (inlined std::ptr::read::) { + debug src => _1; + scope 5 { + } + } + } + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs index 18c4653d4c6ea..551afea3ba5a8 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.rs +++ b/tests/mir-opt/pre-codegen/mem_replace.rs @@ -1,7 +1,8 @@ // skip-filecheck -// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 +// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir // only-64bit // ignore-debug the standard library debug assertions leak into this test +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 26b2663fa3580..4906c86f8ed97 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Enumerate>; - let mut _15: std::iter::Enumerate>; - let mut _16: &mut std::iter::Enumerate>; - let mut _17: std::option::Option<(usize, &T)>; - let mut _18: isize; - let mut _21: &impl Fn(usize, &T); - let mut _22: (usize, &T); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Enumerate>; + let mut _17: std::iter::Enumerate>; + let mut _18: &mut std::iter::Enumerate>; + let mut _19: std::option::Option<(usize, &T)>; + let mut _20: isize; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _17; + let _21: usize; + let _22: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _21; + debug x => _22; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::enumerate) { - debug self => _13; - scope 23 (inlined Enumerate::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::enumerate) { + debug self => _15; + scope 20 (inlined Enumerate::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Enumerate::> { iter: _13, count: const 0_usize }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Enumerate::> { iter: _15, count: const 0_usize }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_17); - StorageLive(_16); - _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind unreachable]; + StorageLive(_19); + StorageLive(_18); + _18 = &mut _17; + _19 = > as Iterator>::next(move _18) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_18); + _20 = discriminant(_19); + switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_19); StorageDead(_17); - StorageDead(_15); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _21 = (((_19 as Some).0: (usize, &T)).0: usize); + _22 = (((_19 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_21, _22); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_17); + StorageDead(_24); + StorageDead(_23); + StorageDead(_19); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index a055612bd5feb..25a5ecdc6c360 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Enumerate>; - let mut _15: std::iter::Enumerate>; - let mut _16: &mut std::iter::Enumerate>; - let mut _17: std::option::Option<(usize, &T)>; - let mut _18: isize; - let mut _21: &impl Fn(usize, &T); - let mut _22: (usize, &T); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Enumerate>; + let mut _17: std::iter::Enumerate>; + let mut _18: &mut std::iter::Enumerate>; + let mut _19: std::option::Option<(usize, &T)>; + let mut _20: isize; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _17; + let _21: usize; + let _22: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _21; + debug x => _22; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::enumerate) { - debug self => _13; - scope 23 (inlined Enumerate::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::enumerate) { + debug self => _15; + scope 20 (inlined Enumerate::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Enumerate::> { iter: _13, count: const 0_usize }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Enumerate::> { iter: _15, count: const 0_usize }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_17); - StorageLive(_16); - _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind: bb11]; + StorageLive(_19); + StorageLive(_18); + _18 = &mut _17; + _19 = > as Iterator>::next(move _18) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_18); + _20 = discriminant(_19); + switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_19); StorageDead(_17); - StorageDead(_15); drop(_2) -> [return: bb7, unwind continue]; } @@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _21 = (((_19 as Some).0: (usize, &T)).0: usize); + _22 = (((_19 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_21, _22); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_17); + StorageDead(_24); + StorageDead(_23); + StorageDead(_19); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 471491108e0b6..133d6f53fce11 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::slice::Iter<'_, T>; - let mut _15: &mut std::slice::Iter<'_, T>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::slice::Iter<'_, T>; + let mut _17: &mut std::slice::Iter<'_, T>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _16; + let _20: &T; scope 2 { - debug x => _18; + debug x => _20; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _22: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _22; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _22; - let mut _23: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _23; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _23; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _23; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as IntoIterator>::into_iter) { - debug self => _13; + scope 19 (inlined as IntoIterator>::into_iter) { + debug self => _15; } bb0: { - StorageLive(_4); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_22); - StorageLive(_23); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_23); - StorageDead(_22); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); StorageLive(_14); _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); + StorageDead(_13); + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + StorageLive(_16); + _16 = _15; goto -> bb4; } bb4: { - StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; + StorageLive(_18); + StorageLive(_17); + _17 = &mut _16; + _18 = as Iterator>::next(move _17) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_18); StorageDead(_16); - StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); - StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; + _20 = ((_18 as Some).0: &T); + StorageLive(_21); + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_20); - StorageDead(_19); - StorageDead(_16); + StorageDead(_22); + StorageDead(_21); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index bbf38aba91f08..4e74253e54172 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::slice::Iter<'_, T>; - let mut _15: &mut std::slice::Iter<'_, T>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::slice::Iter<'_, T>; + let mut _17: &mut std::slice::Iter<'_, T>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _16; + let _20: &T; scope 2 { - debug x => _18; + debug x => _20; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _22: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _22; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _22; - let mut _23: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _23; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _23; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _23; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as IntoIterator>::into_iter) { - debug self => _13; + scope 19 (inlined as IntoIterator>::into_iter) { + debug self => _15; } bb0: { - StorageLive(_4); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_22); - StorageLive(_23); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_23); - StorageDead(_22); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); StorageLive(_14); _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); + StorageDead(_13); + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + StorageLive(_16); + _16 = _15; goto -> bb4; } bb4: { - StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + StorageLive(_18); + StorageLive(_17); + _17 = &mut _16; + _18 = as Iterator>::next(move _17) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_18); StorageDead(_16); - StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); - StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _20 = ((_18 as Some).0: &T); + StorageLive(_21); + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_20); - StorageDead(_19); - StorageDead(_16); + StorageDead(_22); + StorageDead(_21); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index f9c8ab4db60b7..639e1a51430db 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Rev>; - let mut _15: std::iter::Rev>; - let mut _16: &mut std::iter::Rev>; - let mut _18: std::option::Option<&T>; - let mut _19: isize; - let mut _21: &impl Fn(&T); - let mut _22: (&T,); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Rev>; + let mut _17: std::iter::Rev>; + let mut _18: &mut std::iter::Rev>; + let mut _20: std::option::Option<&T>; + let mut _21: isize; + let mut _23: &impl Fn(&T); + let mut _24: (&T,); + let _25: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _17; + let _22: &T; scope 2 { - debug x => _20; + debug x => _22; } - scope 25 (inlined > as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + scope 22 (inlined > as Iterator>::next) { + debug self => _18; + let mut _19: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::rev) { - debug self => _13; - scope 23 (inlined Rev::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::rev) { + debug self => _15; + scope 20 (inlined Rev::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Rev::> { iter: _13 }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Rev::> { iter: _15 }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; - StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable]; + StorageLive(_20); + _18 = &mut _17; + StorageLive(_19); + _19 = &mut (_17.0: std::slice::Iter<'_, T>); + _20 = as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_19); + _21 = discriminant(_20); + switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_20); + StorageDead(_17); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _22 = ((_20 as Some).0: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_22,); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_18); + StorageDead(_24); + StorageDead(_23); + StorageDead(_20); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 65f423ac326be..2237fd7dbd12c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Rev>; - let mut _15: std::iter::Rev>; - let mut _16: &mut std::iter::Rev>; - let mut _18: std::option::Option<&T>; - let mut _19: isize; - let mut _21: &impl Fn(&T); - let mut _22: (&T,); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Rev>; + let mut _17: std::iter::Rev>; + let mut _18: &mut std::iter::Rev>; + let mut _20: std::option::Option<&T>; + let mut _21: isize; + let mut _23: &impl Fn(&T); + let mut _24: (&T,); + let _25: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _17; + let _22: &T; scope 2 { - debug x => _20; + debug x => _22; } - scope 25 (inlined > as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + scope 22 (inlined > as Iterator>::next) { + debug self => _18; + let mut _19: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::rev) { - debug self => _13; - scope 23 (inlined Rev::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::rev) { + debug self => _15; + scope 20 (inlined Rev::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Rev::> { iter: _13 }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Rev::> { iter: _15 }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; - StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11]; + StorageLive(_20); + _18 = &mut _17; + StorageLive(_19); + _19 = &mut (_17.0: std::slice::Iter<'_, T>); + _20 = as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_19); + _21 = discriminant(_20); + switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_20); + StorageDead(_17); drop(_2) -> [return: bb7, unwind continue]; } @@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _22 = ((_20 as Some).0: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_22,); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_18); + StorageDead(_24); + StorageDead(_23); + StorageDead(_20); goto -> bb4; } diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5824ef31211be..5c552411da7f3 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:570:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From dbf817bae1f25f0fa2fbb1e40ab74afc892d9a60 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 8 Feb 2024 11:11:13 -0500 Subject: [PATCH 10/10] Add and use Unique::as_non_null_ptr --- library/core/src/ptr/non_null.rs | 6 ++---- library/core/src/ptr/unique.rs | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 575af96fc982f..320cd5eb3b2ae 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1591,8 +1591,7 @@ impl NonNull<[T]> { #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] pub const fn as_non_null_ptr(self) -> NonNull { - // SAFETY: We know `self` is non-null. - unsafe { NonNull::new_unchecked(self.as_ptr().as_mut_ptr()) } + self.cast() } /// Returns a raw pointer to the slice's buffer. @@ -1828,8 +1827,7 @@ impl hash::Hash for NonNull { impl From> for NonNull { #[inline] fn from(unique: Unique) -> Self { - // SAFETY: A Unique pointer cannot be null. - unsafe { NonNull { pointer: unique.as_ptr() } } + unique.as_non_null_ptr() } } diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 2d878836b1627..b74d691e45427 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -106,6 +106,13 @@ impl Unique { self.pointer.as_ptr() } + /// Acquires the underlying `*mut` pointer. + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub const fn as_non_null_ptr(self) -> NonNull { + self.pointer + } + /// Dereferences the content. /// /// The resulting lifetime is bound to self so this behaves "as if"