Auto merge of #120594 - saethlin:delayed-debug-asserts, r=oli-obk
Toggle assert_unsafe_precondition in codegen instead of expansion The goal of this PR is to make some of the unsafe precondition checks in the standard library available in debug builds. Some UI tests are included to verify that it does that. The diff is large, but most of it is blessing mir-opt tests and I've also split up this PR so it can be reviewed commit-by-commit. This PR: 1. Adds a new intrinsic, `debug_assertions` which is lowered to a new MIR NullOp, and only to a constant after monomorphization 2. Rewrites `assume_unsafe_precondition` to check the new intrinsic, and be monomorphic. 3. Skips codegen of the `assume` intrinsic in unoptimized builds, because that was silly before but with these checks it's *very* silly 4. The checks with the most overhead are `ptr::read`/`ptr::write` and `NonNull::new_unchecked`. I've simply added `#[cfg(debug_assertions)]` to the checks for `ptr::read`/`ptr::write` because I was unable to come up with any (good) ideas for decreasing their impact. But for `NonNull::new_unchecked` I found that the majority of callers can use a different function, often a safe one. Yes, this PR slows down the compile time of some programs. But in our benchmark suite it's never more than 1% icount, and the average icount change in debug-full programs is 0.22%. I think that is acceptable for such an improvement in developer experience. https://github.com/rust-lang/rust/issues/120539#issuecomment-1922687101
This commit is contained in:
commit
8fb67fb37f
65 changed files with 1480 additions and 1293 deletions
|
@ -1983,6 +1983,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
ConstraintCategory::SizedBound,
|
ConstraintCategory::SizedBound,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
&Rvalue::NullaryOp(NullOp::DebugAssertions, _) => {}
|
||||||
|
|
||||||
Rvalue::ShallowInitBox(operand, ty) => {
|
Rvalue::ShallowInitBox(operand, ty) => {
|
||||||
self.check_operand(operand, location);
|
self.check_operand(operand, location);
|
||||||
|
|
|
@ -767,6 +767,15 @@ fn codegen_stmt<'tcx>(
|
||||||
NullOp::OffsetOf(fields) => {
|
NullOp::OffsetOf(fields) => {
|
||||||
layout.offset_of_subfield(fx, fields.iter()).bytes()
|
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(
|
let val = CValue::by_val(
|
||||||
fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()),
|
fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()),
|
||||||
|
|
|
@ -672,17 +672,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
let val = match null_op {
|
let val = match null_op {
|
||||||
mir::NullOp::SizeOf => {
|
mir::NullOp::SizeOf => {
|
||||||
assert!(bx.cx().type_is_sized(ty));
|
assert!(bx.cx().type_is_sized(ty));
|
||||||
layout.size.bytes()
|
let val = layout.size.bytes();
|
||||||
|
bx.cx().const_usize(val)
|
||||||
}
|
}
|
||||||
mir::NullOp::AlignOf => {
|
mir::NullOp::AlignOf => {
|
||||||
assert!(bx.cx().type_is_sized(ty));
|
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) => {
|
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();
|
let tcx = self.cx.tcx();
|
||||||
OperandRef {
|
OperandRef {
|
||||||
val: OperandValue::Immediate(val),
|
val: OperandValue::Immediate(val),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::NonDivergingIntrinsic;
|
use rustc_middle::mir::NonDivergingIntrinsic;
|
||||||
|
use rustc_session::config::OptLevel;
|
||||||
|
|
||||||
use super::FunctionCx;
|
use super::FunctionCx;
|
||||||
use super::LocalRef;
|
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);
|
self.codegen_coverage(bx, coverage, statement.source_info.scope);
|
||||||
}
|
}
|
||||||
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
|
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
|
||||||
let op_val = self.codegen_operand(bx, op);
|
if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) {
|
||||||
bx.assume(op_val.immediate());
|
let op_val = self.codegen_operand(bx, op);
|
||||||
|
bx.assume(op_val.immediate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
|
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
|
||||||
mir::CopyNonOverlapping { ref count, ref src, ref dst },
|
mir::CopyNonOverlapping { ref count, ref src, ref dst },
|
||||||
|
|
|
@ -246,13 +246,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let val = match null_op {
|
let val = match null_op {
|
||||||
mir::NullOp::SizeOf => layout.size.bytes(),
|
mir::NullOp::SizeOf => {
|
||||||
mir::NullOp::AlignOf => layout.align.abi.bytes(),
|
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) => {
|
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, _) => {
|
ShallowInitBox(ref operand, _) => {
|
||||||
|
|
|
@ -544,7 +544,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
|
|
||||||
Rvalue::Cast(_, _, _) => {}
|
Rvalue::Cast(_, _, _) => {}
|
||||||
|
|
||||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {}
|
Rvalue::NullaryOp(
|
||||||
|
NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions,
|
||||||
|
_,
|
||||||
|
) => {}
|
||||||
Rvalue::ShallowInitBox(_, _) => {}
|
Rvalue::ShallowInitBox(_, _) => {}
|
||||||
|
|
||||||
Rvalue::UnaryOp(_, operand) => {
|
Rvalue::UnaryOp(_, operand) => {
|
||||||
|
|
|
@ -1139,7 +1139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
Rvalue::Repeat(_, _)
|
Rvalue::Repeat(_, _)
|
||||||
| Rvalue::ThreadLocalRef(_)
|
| Rvalue::ThreadLocalRef(_)
|
||||||
| Rvalue::AddressOf(_, _)
|
| Rvalue::AddressOf(_, _)
|
||||||
| Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
|
| Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::DebugAssertions, _)
|
||||||
| Rvalue::Discriminant(_) => {}
|
| Rvalue::Discriminant(_) => {}
|
||||||
}
|
}
|
||||||
self.super_rvalue(rvalue, location);
|
self.super_rvalue(rvalue, location);
|
||||||
|
|
|
@ -112,7 +112,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
|
||||||
| sym::forget
|
| sym::forget
|
||||||
| sym::black_box
|
| sym::black_box
|
||||||
| sym::variant_count
|
| sym::variant_count
|
||||||
| sym::ptr_mask => hir::Unsafety::Normal,
|
| sym::ptr_mask
|
||||||
|
| sym::debug_assertions => hir::Unsafety::Normal,
|
||||||
_ => hir::Unsafety::Unsafe,
|
_ => 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)
|
(0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sym::debug_assertions => (0, Vec::new(), tcx.types.bool),
|
||||||
|
|
||||||
other => {
|
other => {
|
||||||
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
|
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -907,6 +907,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
NullOp::SizeOf => write!(fmt, "SizeOf({t})"),
|
NullOp::SizeOf => write!(fmt, "SizeOf({t})"),
|
||||||
NullOp::AlignOf => write!(fmt, "AlignOf({t})"),
|
NullOp::AlignOf => write!(fmt, "AlignOf({t})"),
|
||||||
NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"),
|
NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"),
|
||||||
|
NullOp::DebugAssertions => write!(fmt, "cfg!(debug_assertions)"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ThreadLocalRef(did) => ty::tls::with(|tcx| {
|
ThreadLocalRef(did) => ty::tls::with(|tcx| {
|
||||||
|
|
|
@ -1361,6 +1361,8 @@ pub enum NullOp<'tcx> {
|
||||||
AlignOf,
|
AlignOf,
|
||||||
/// Returns the offset of a field
|
/// Returns the offset of a field
|
||||||
OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>),
|
OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>),
|
||||||
|
/// cfg!(debug_assertions), but expanded in codegen
|
||||||
|
DebugAssertions,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
|
@ -194,6 +194,7 @@ impl<'tcx> Rvalue<'tcx> {
|
||||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
|
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
|
||||||
tcx.types.usize
|
tcx.types.usize
|
||||||
}
|
}
|
||||||
|
Rvalue::NullaryOp(NullOp::DebugAssertions, _) => tcx.types.bool,
|
||||||
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
|
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
|
||||||
AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
|
AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
|
||||||
AggregateKind::Tuple => {
|
AggregateKind::Tuple => {
|
||||||
|
|
|
@ -429,7 +429,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
|
||||||
| Rvalue::AddressOf(..)
|
| Rvalue::AddressOf(..)
|
||||||
| Rvalue::Discriminant(..)
|
| Rvalue::Discriminant(..)
|
||||||
| Rvalue::Len(..)
|
| Rvalue::Len(..)
|
||||||
| Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {}
|
| Rvalue::NullaryOp(
|
||||||
|
NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::DebugAssertions,
|
||||||
|
_,
|
||||||
|
) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -634,6 +634,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
NullOp::OffsetOf(fields) => {
|
NullOp::OffsetOf(fields) => {
|
||||||
op_layout.offset_of_subfield(self, fields.iter()).bytes()
|
op_layout.offset_of_subfield(self, fields.iter()).bytes()
|
||||||
}
|
}
|
||||||
|
NullOp::DebugAssertions => return None,
|
||||||
};
|
};
|
||||||
ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into()
|
ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -489,6 +489,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
NullOp::OffsetOf(fields) => {
|
NullOp::OffsetOf(fields) => {
|
||||||
layout.offset_of_subfield(&self.ecx, fields.iter()).bytes()
|
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 usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
|
||||||
let imm = ImmTy::try_from_uint(val, usize_layout)?;
|
let imm = ImmTy::try_from_uint(val, usize_layout)?;
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
use crate::simplify::simplify_duplicate_switch_targets;
|
use crate::simplify::simplify_duplicate_switch_targets;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
|
use rustc_middle::ty::layout;
|
||||||
use rustc_middle::ty::layout::ValidityRequirement;
|
use rustc_middle::ty::layout::ValidityRequirement;
|
||||||
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::abi::FieldIdx;
|
use rustc_target::abi::FieldIdx;
|
||||||
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
pub struct InstSimplify;
|
pub struct InstSimplify;
|
||||||
|
|
||||||
|
@ -38,6 +40,7 @@ impl<'tcx> MirPass<'tcx> for InstSimplify {
|
||||||
block.terminator.as_mut().unwrap(),
|
block.terminator.as_mut().unwrap(),
|
||||||
&mut block.statements,
|
&mut block.statements,
|
||||||
);
|
);
|
||||||
|
ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap());
|
||||||
simplify_duplicate_switch_targets(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 };
|
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(
|
fn simplify_intrinsic_assert(
|
||||||
&self,
|
&self,
|
||||||
terminator: &mut Terminator<'tcx>,
|
terminator: &mut Terminator<'tcx>,
|
||||||
|
|
|
@ -21,6 +21,17 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||||
sym::unreachable => {
|
sym::unreachable => {
|
||||||
terminator.kind = TerminatorKind::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 => {
|
sym::forget => {
|
||||||
if let Some(target) = *target {
|
if let Some(target) = *target {
|
||||||
block.statements.push(Statement {
|
block.statements.push(Statement {
|
||||||
|
|
|
@ -446,6 +446,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||||
NullOp::SizeOf => {}
|
NullOp::SizeOf => {}
|
||||||
NullOp::AlignOf => {}
|
NullOp::AlignOf => {}
|
||||||
NullOp::OffsetOf(_) => {}
|
NullOp::OffsetOf(_) => {}
|
||||||
|
NullOp::DebugAssertions => {}
|
||||||
},
|
},
|
||||||
|
|
||||||
Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
|
Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
|
||||||
|
|
|
@ -257,6 +257,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
|
||||||
OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf(
|
OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf(
|
||||||
indices.iter().map(|idx| idx.stable(tables)).collect(),
|
indices.iter().map(|idx| idx.stable(tables)).collect(),
|
||||||
),
|
),
|
||||||
|
DebugAssertions => stable_mir::mir::NullOp::DebugAssertions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -639,6 +639,7 @@ impl Rvalue {
|
||||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
|
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
|
||||||
Ok(Ty::usize_ty())
|
Ok(Ty::usize_ty())
|
||||||
}
|
}
|
||||||
|
Rvalue::NullaryOp(NullOp::DebugAssertions, _) => Ok(Ty::bool_ty()),
|
||||||
Rvalue::Aggregate(ak, ops) => match *ak {
|
Rvalue::Aggregate(ak, ops) => match *ak {
|
||||||
AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64),
|
AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64),
|
||||||
AggregateKind::Tuple => Ok(Ty::new_tuple(
|
AggregateKind::Tuple => Ok(Ty::new_tuple(
|
||||||
|
@ -1005,6 +1006,8 @@ pub enum NullOp {
|
||||||
AlignOf,
|
AlignOf,
|
||||||
/// Returns the offset of a field.
|
/// Returns the offset of a field.
|
||||||
OffsetOf(Vec<(VariantIdx, FieldIdx)>),
|
OffsetOf(Vec<(VariantIdx, FieldIdx)>),
|
||||||
|
/// cfg!(debug_assertions), but at codegen time
|
||||||
|
DebugAssertions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operand {
|
impl Operand {
|
||||||
|
|
|
@ -207,11 +207,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
||||||
// Allocators currently return a `NonNull<[u8]>` whose length
|
// Allocators currently return a `NonNull<[u8]>` whose length
|
||||||
// matches the size requested. If that ever changes, the capacity
|
// matches the size requested. If that ever changes, the capacity
|
||||||
// here should change to `ptr.len() / mem::size_of::<T>()`.
|
// here should change to `ptr.len() / mem::size_of::<T>()`.
|
||||||
Self {
|
Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }
|
||||||
ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) },
|
|
||||||
cap: unsafe { Cap(capacity) },
|
|
||||||
alloc,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,6 +235,11 @@ impl<T, A: Allocator> RawVec<T, A> {
|
||||||
self.ptr.as_ptr()
|
self.ptr.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn non_null(&self) -> NonNull<T> {
|
||||||
|
NonNull::from(self.ptr)
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the capacity of the allocation.
|
/// Gets the capacity of the allocation.
|
||||||
///
|
///
|
||||||
/// This will always be `usize::MAX` if `T` is zero-sized.
|
/// This will always be `usize::MAX` if `T` is zero-sized.
|
||||||
|
@ -398,7 +399,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
||||||
// Allocators currently return a `NonNull<[u8]>` whose length matches
|
// Allocators currently return a `NonNull<[u8]>` whose length matches
|
||||||
// the size requested. If that ever changes, the capacity here should
|
// the size requested. If that ever changes, the capacity here should
|
||||||
// change to `ptr.len() / mem::size_of::<T>()`.
|
// change to `ptr.len() / mem::size_of::<T>()`.
|
||||||
self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) };
|
self.ptr = Unique::from(ptr.cast());
|
||||||
self.cap = unsafe { Cap(cap) };
|
self.cap = unsafe { Cap(cap) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
|
||||||
// struct and then overwriting &mut self.
|
// struct and then overwriting &mut self.
|
||||||
// this creates less assembly
|
// this creates less assembly
|
||||||
self.cap = 0;
|
self.cap = 0;
|
||||||
self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
|
self.buf = RawVec::NEW.non_null();
|
||||||
self.ptr = self.buf;
|
self.ptr = self.buf;
|
||||||
self.end = self.buf.as_ptr();
|
self.end = self.buf.as_ptr();
|
||||||
|
|
||||||
|
|
|
@ -2861,16 +2861,16 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut me = ManuallyDrop::new(self);
|
let me = ManuallyDrop::new(self);
|
||||||
let alloc = ManuallyDrop::new(ptr::read(me.allocator()));
|
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 {
|
let end = if T::IS_ZST {
|
||||||
begin.wrapping_byte_add(me.len())
|
begin.wrapping_byte_add(me.len())
|
||||||
} else {
|
} else {
|
||||||
begin.add(me.len()) as *const T
|
begin.add(me.len()) as *const T
|
||||||
};
|
};
|
||||||
let cap = me.buf.capacity();
|
let cap = me.buf.capacity();
|
||||||
let buf = NonNull::new_unchecked(begin);
|
|
||||||
IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end }
|
IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"invalid value for `char`",
|
"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)
|
transmute(i)
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ pub const unsafe fn assert_unchecked(cond: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
intrinsics::assert_unsafe_precondition!(
|
intrinsics::assert_unsafe_precondition!(
|
||||||
"hint::assert_unchecked must never be called when the condition is false",
|
"hint::assert_unchecked must never be called when the condition is false",
|
||||||
(cond: bool) => cond,
|
(cond: bool = cond) => cond,
|
||||||
);
|
);
|
||||||
crate::intrinsics::assume(cond);
|
crate::intrinsics::assume(cond);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
|
|
||||||
use crate::marker::DiscriminantKind;
|
use crate::marker::DiscriminantKind;
|
||||||
use crate::marker::Tuple;
|
use crate::marker::Tuple;
|
||||||
use crate::mem;
|
use crate::mem::{self, align_of};
|
||||||
|
|
||||||
pub mod mir;
|
pub mod mir;
|
||||||
pub mod simd;
|
pub mod simd;
|
||||||
|
@ -2569,6 +2569,17 @@ extern "rust-intrinsic" {
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[cfg(not(bootstrap))]
|
#[cfg(not(bootstrap))]
|
||||||
pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
|
pub fn is_val_statically_known<T: Copy>(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`
|
// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable`
|
||||||
|
@ -2587,10 +2598,27 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
|
||||||
/// Check that the preconditions of an unsafe function are followed, if debug_assertions are on,
|
/// Check that the preconditions of an unsafe function are followed, if debug_assertions are on,
|
||||||
/// and only at runtime.
|
/// and only at runtime.
|
||||||
///
|
///
|
||||||
/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)`
|
/// This macro should be called as
|
||||||
/// where the names specified will be moved into the macro as captured variables, and defines an item
|
/// `assert_unsafe_precondition!((expr => name: Type, expr => name: Type) => Expression)`
|
||||||
/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics
|
/// where each `expr` will be evaluated and passed in as function argument `name: Type`. Then all
|
||||||
/// for the function declarations and can be omitted if there is no generics.
|
/// 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
|
/// # Safety
|
||||||
///
|
///
|
||||||
|
@ -2604,26 +2632,24 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
|
||||||
///
|
///
|
||||||
/// So in a sense it is UB if this macro is useful, but we expect callers of `unsafe fn` to make
|
/// 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.
|
/// 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 {
|
macro_rules! assert_unsafe_precondition {
|
||||||
($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => {
|
($message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => {
|
||||||
if cfg!(debug_assertions) {
|
{
|
||||||
// allow non_snake_case to allow capturing const generics
|
#[inline(never)]
|
||||||
#[allow(non_snake_case)]
|
#[rustc_nounwind]
|
||||||
#[inline(always)]
|
fn precondition_check($($name:$ty),*) {
|
||||||
fn runtime$(<$($tt)*>)?($($i:$ty),*) {
|
|
||||||
if !$e {
|
if !$e {
|
||||||
// don't unwind to reduce impact on code size
|
|
||||||
::core::panicking::panic_nounwind(
|
::core::panicking::panic_nounwind(
|
||||||
concat!("unsafe precondition(s) violated: ", $name)
|
concat!("unsafe precondition(s) violated: ", $message)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(non_snake_case)]
|
const fn comptime($(_:$ty),*) {}
|
||||||
#[inline]
|
|
||||||
const fn comptime$(<$($tt)*>)?($(_:$ty),*) {}
|
|
||||||
|
|
||||||
::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime);
|
if ::core::intrinsics::debug_assertions() {
|
||||||
|
::core::intrinsics::const_eval_select(($($arg,)*), comptime, precondition_check);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2632,30 +2658,47 @@ pub(crate) use assert_unsafe_precondition;
|
||||||
/// Checks whether `ptr` is properly aligned with respect to
|
/// Checks whether `ptr` is properly aligned with respect to
|
||||||
/// `align_of::<T>()`.
|
/// `align_of::<T>()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
|
pub(crate) fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool {
|
||||||
!ptr.is_null() && ptr.is_aligned()
|
!ptr.is_null() && ptr.is_aligned_to(align)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether an allocation of `len` instances of `T` exceeds
|
|
||||||
/// the maximum allowed allocation size.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
|
pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool {
|
||||||
let max_len = const {
|
let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size };
|
||||||
let size = crate::mem::size_of::<T>();
|
|
||||||
if size == 0 { usize::MAX } else { isize::MAX as usize / size }
|
|
||||||
};
|
|
||||||
len <= max_len
|
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::<T>() * 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
|
/// Checks whether the regions of memory starting at `src` and `dst` of size
|
||||||
/// `count * size_of::<T>()` do *not* overlap.
|
/// `count * size_of::<T>()` do *not* overlap.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
|
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
|
||||||
let src_usize = src.addr();
|
let src_usize = src.addr();
|
||||||
let dst_usize = dst.addr();
|
let dst_usize = dst.addr();
|
||||||
let size = mem::size_of::<T>()
|
let Some(size) = mem::size_of::<T>().checked_mul(count) else {
|
||||||
.checked_mul(count)
|
// Use panic_nounwind instead of Option::expect, so that this function is nounwind.
|
||||||
.expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize");
|
crate::panicking::panic_nounwind(
|
||||||
|
"is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
|
||||||
|
)
|
||||||
|
};
|
||||||
let diff = src_usize.abs_diff(dst_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,
|
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
|
||||||
// they do not overlap.
|
// they do not overlap.
|
||||||
|
@ -2766,10 +2809,16 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
|
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
|
||||||
and the specified memory ranges do not overlap",
|
and the specified memory ranges do not overlap",
|
||||||
[T](src: *const T, dst: *mut T, count: usize) =>
|
(
|
||||||
is_aligned_and_not_null(src)
|
src: *const () = src as *const (),
|
||||||
&& is_aligned_and_not_null(dst)
|
dst: *mut () = dst as *mut (),
|
||||||
&& is_nonoverlapping(src, dst, count)
|
size: usize = size_of::<T>(),
|
||||||
|
align: usize = align_of::<T>(),
|
||||||
|
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)
|
copy_nonoverlapping(src, dst, count)
|
||||||
}
|
}
|
||||||
|
@ -2859,9 +2908,15 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||||
// SAFETY: the safety contract for `copy` must be upheld by the caller.
|
// SAFETY: the safety contract for `copy` must be upheld by the caller.
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::copy requires that both pointer arguments are aligned and non-null",
|
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
|
||||||
[T](src: *const T, dst: *mut T) =>
|
and the specified memory ranges do not overlap",
|
||||||
is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)
|
(
|
||||||
|
src: *const () = src as *const (),
|
||||||
|
dst: *mut () = dst as *mut (),
|
||||||
|
align: usize = align_of::<T>(),
|
||||||
|
) =>
|
||||||
|
is_aligned_and_not_null(src, align)
|
||||||
|
&& is_aligned_and_not_null(dst, align)
|
||||||
);
|
);
|
||||||
copy(src, dst, count)
|
copy(src, dst, count)
|
||||||
}
|
}
|
||||||
|
@ -2934,7 +2989,10 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::write_bytes requires that the destination pointer is aligned and non-null",
|
"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::<T>(),
|
||||||
|
) => is_aligned_and_not_null(addr, align)
|
||||||
);
|
);
|
||||||
write_bytes(dst, val, count)
|
write_bytes(dst, val, count)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1033,7 +1033,6 @@ impl<T> Option<T> {
|
||||||
#[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
|
#[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
|
||||||
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
|
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
|
||||||
pub const unsafe fn unwrap_unchecked(self) -> T {
|
pub const unsafe fn unwrap_unchecked(self) -> T {
|
||||||
debug_assert!(self.is_some());
|
|
||||||
match self {
|
match self {
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
// SAFETY: the safety contract must be upheld by the caller.
|
// SAFETY: the safety contract must be upheld by the caller.
|
||||||
|
|
|
@ -806,13 +806,15 @@ impl<T: ?Sized> *const T {
|
||||||
where
|
where
|
||||||
T: Sized,
|
T: Sized,
|
||||||
{
|
{
|
||||||
let this = self;
|
|
||||||
// SAFETY: The comparison has no side-effects, and the intrinsic
|
// SAFETY: The comparison has no side-effects, and the intrinsic
|
||||||
// does this check internally in the CTFE implementation.
|
// does this check internally in the CTFE implementation.
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::sub_ptr requires `this >= origin`",
|
"ptr::sub_ptr requires `self >= origin`",
|
||||||
[T](this: *const T, origin: *const T) => this >= origin
|
(
|
||||||
|
this: *const () = self as *const (),
|
||||||
|
origin: *const () = origin as *const (),
|
||||||
|
) => this >= origin
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -381,11 +381,11 @@ use crate::cmp::Ordering;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::hash;
|
use crate::hash;
|
||||||
use crate::intrinsics::{
|
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::marker::FnPtr;
|
||||||
|
|
||||||
use crate::mem::{self, MaybeUninit};
|
use crate::mem::{self, align_of, size_of, MaybeUninit};
|
||||||
|
|
||||||
mod alignment;
|
mod alignment;
|
||||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
|
@ -967,10 +967,16 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \
|
"ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \
|
||||||
and the specified memory ranges do not overlap",
|
and the specified memory ranges do not overlap",
|
||||||
[T](x: *mut T, y: *mut T, count: usize) =>
|
(
|
||||||
is_aligned_and_not_null(x)
|
x: *mut () = x as *mut (),
|
||||||
&& is_aligned_and_not_null(y)
|
y: *mut () = y as *mut (),
|
||||||
&& is_nonoverlapping(x, y, count)
|
size: usize = size_of::<T>(),
|
||||||
|
align: usize = align_of::<T>(),
|
||||||
|
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<T>(dst: *mut T, mut src: T) -> T {
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::replace requires that the pointer argument is aligned and non-null",
|
"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::<T>(),
|
||||||
|
) => is_aligned_and_not_null(addr, align)
|
||||||
);
|
);
|
||||||
mem::swap(&mut *dst, &mut src); // cannot overlap
|
mem::swap(&mut *dst, &mut src); // cannot overlap
|
||||||
}
|
}
|
||||||
|
@ -1207,9 +1216,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
|
||||||
|
|
||||||
// SAFETY: the caller must guarantee that `src` is valid for reads.
|
// SAFETY: the caller must guarantee that `src` is valid for reads.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
#[cfg(debug_assertions)] // Too expensive to always enable (for now?)
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::read requires that the pointer argument is aligned and non-null",
|
"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::<T>(),
|
||||||
|
) => is_aligned_and_not_null(addr, align)
|
||||||
);
|
);
|
||||||
crate::intrinsics::read_via_copy(src)
|
crate::intrinsics::read_via_copy(src)
|
||||||
}
|
}
|
||||||
|
@ -1411,9 +1424,13 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
|
||||||
// `dst` cannot overlap `src` because the caller has mutable access
|
// `dst` cannot overlap `src` because the caller has mutable access
|
||||||
// to `dst` while `src` is owned by this function.
|
// to `dst` while `src` is owned by this function.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
#[cfg(debug_assertions)] // Too expensive to always enable (for now?)
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::write requires that the pointer argument is aligned and non-null",
|
"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::<T>(),
|
||||||
|
) => is_aligned_and_not_null(addr, align)
|
||||||
);
|
);
|
||||||
intrinsics::write_via_move(dst, src)
|
intrinsics::write_via_move(dst, src)
|
||||||
}
|
}
|
||||||
|
@ -1581,7 +1598,10 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::read_volatile requires that the pointer argument is aligned and non-null",
|
"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::<T>(),
|
||||||
|
) => is_aligned_and_not_null(addr, align)
|
||||||
);
|
);
|
||||||
intrinsics::volatile_load(src)
|
intrinsics::volatile_load(src)
|
||||||
}
|
}
|
||||||
|
@ -1656,7 +1676,10 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
"ptr::write_volatile requires that the pointer argument is aligned and non-null",
|
"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::<T>(),
|
||||||
|
) => is_aligned_and_not_null(addr, align)
|
||||||
);
|
);
|
||||||
intrinsics::volatile_store(dst, src);
|
intrinsics::volatile_store(dst, src);
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,7 +218,10 @@ impl<T: ?Sized> NonNull<T> {
|
||||||
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
||||||
// SAFETY: the caller must guarantee that `ptr` is non-null.
|
// SAFETY: the caller must guarantee that `ptr` is non-null.
|
||||||
unsafe {
|
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 _ }
|
NonNull { pointer: ptr as _ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,7 +473,7 @@ impl<T: ?Sized> NonNull<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn cast<U>(self) -> NonNull<U> {
|
pub const fn cast<U>(self) -> NonNull<U> {
|
||||||
// SAFETY: `self` is a `NonNull` pointer which is necessarily non-null
|
// 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.
|
/// Calculates the offset from a pointer.
|
||||||
|
@ -1588,8 +1591,7 @@ impl<T> NonNull<[T]> {
|
||||||
#[unstable(feature = "slice_ptr_get", issue = "74265")]
|
#[unstable(feature = "slice_ptr_get", issue = "74265")]
|
||||||
#[rustc_const_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<T> {
|
pub const fn as_non_null_ptr(self) -> NonNull<T> {
|
||||||
// SAFETY: We know `self` is non-null.
|
self.cast()
|
||||||
unsafe { NonNull::new_unchecked(self.as_ptr().as_mut_ptr()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a raw pointer to the slice's buffer.
|
/// Returns a raw pointer to the slice's buffer.
|
||||||
|
@ -1825,9 +1827,7 @@ impl<T: ?Sized> hash::Hash for NonNull<T> {
|
||||||
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(unique: Unique<T>) -> Self {
|
fn from(unique: Unique<T>) -> Self {
|
||||||
// SAFETY: A Unique pointer cannot be null, so the conditions for
|
unique.as_non_null_ptr()
|
||||||
// new_unchecked() are respected.
|
|
||||||
unsafe { NonNull::new_unchecked(unique.as_ptr()) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1850,8 +1850,7 @@ impl<T: ?Sized> From<&T> for NonNull<T> {
|
||||||
/// This conversion is safe and infallible since references cannot be null.
|
/// This conversion is safe and infallible since references cannot be null.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(reference: &T) -> Self {
|
fn from(reference: &T) -> Self {
|
||||||
// SAFETY: A reference cannot be null, so the conditions for
|
// SAFETY: A reference cannot be null.
|
||||||
// new_unchecked() are respected.
|
|
||||||
unsafe { NonNull { pointer: reference as *const T } }
|
unsafe { NonNull { pointer: reference as *const T } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,13 @@ impl<T: ?Sized> Unique<T> {
|
||||||
self.pointer.as_ptr()
|
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<T> {
|
||||||
|
self.pointer
|
||||||
|
}
|
||||||
|
|
||||||
/// Dereferences the content.
|
/// Dereferences the content.
|
||||||
///
|
///
|
||||||
/// The resulting lifetime is bound to self so this behaves "as if"
|
/// The resulting lifetime is bound to self so this behaves "as if"
|
||||||
|
@ -138,7 +145,7 @@ impl<T: ?Sized> Unique<T> {
|
||||||
pub const fn cast<U>(self) -> Unique<U> {
|
pub const fn cast<U>(self) -> Unique<U> {
|
||||||
// FIXME(const-hack): replace with `From`
|
// FIXME(const-hack): replace with `From`
|
||||||
// SAFETY: is `NonNull`
|
// SAFETY: is `NonNull`
|
||||||
unsafe { Unique::new_unchecked(self.pointer.cast().as_ptr()) }
|
Unique { pointer: self.pointer.cast(), _marker: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,12 +87,13 @@ unsafe impl<T: Sync> Send for Iter<'_, T> {}
|
||||||
impl<'a, T> Iter<'a, T> {
|
impl<'a, T> Iter<'a, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn new(slice: &'a [T]) -> Self {
|
pub(super) fn new(slice: &'a [T]) -> Self {
|
||||||
let ptr = slice.as_ptr();
|
let len = slice.len();
|
||||||
|
let ptr: NonNull<T> = NonNull::from(slice).cast();
|
||||||
// SAFETY: Similar to `IterMut::new`.
|
// SAFETY: Similar to `IterMut::new`.
|
||||||
unsafe {
|
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<T: Send> Send for IterMut<'_, T> {}
|
||||||
impl<'a, T> IterMut<'a, T> {
|
impl<'a, T> IterMut<'a, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn new(slice: &'a mut [T]) -> Self {
|
pub(super) fn new(slice: &'a mut [T]) -> Self {
|
||||||
let ptr = slice.as_mut_ptr();
|
let len = slice.len();
|
||||||
|
let ptr: NonNull<T> = NonNull::from(slice).cast();
|
||||||
// SAFETY: There are several things here:
|
// SAFETY: There are several things here:
|
||||||
//
|
//
|
||||||
// `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid
|
// `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
|
// See the `next_unchecked!` and `is_empty!` macros as well as the
|
||||||
// `post_inc_start` method for more information.
|
// `post_inc_start` method for more information.
|
||||||
unsafe {
|
unsafe {
|
||||||
let end_or_len =
|
let end_or_len = if T::IS_ZST { invalid_mut(len) } else { ptr.as_ptr().add(len) };
|
||||||
if T::IS_ZST { invalid_mut(slice.len()) } else { ptr.add(slice.len()) };
|
|
||||||
|
|
||||||
Self { ptr: NonNull::new_unchecked(ptr), end_or_len, _marker: PhantomData }
|
Self { ptr, end_or_len, _marker: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::array;
|
||||||
use crate::intrinsics::{
|
use crate::intrinsics::{
|
||||||
assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size,
|
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::ops::Range;
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
|
|
||||||
|
@ -96,8 +97,14 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
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`",
|
"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::<T>(len)
|
data: *mut () = data as *mut (),
|
||||||
|
size: usize = size_of::<T>(),
|
||||||
|
align: usize = align_of::<T>(),
|
||||||
|
len: usize = len,
|
||||||
|
) =>
|
||||||
|
is_aligned_and_not_null(data, align)
|
||||||
|
&& is_valid_allocation_size(size, len)
|
||||||
);
|
);
|
||||||
&*ptr::slice_from_raw_parts(data, 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 {
|
unsafe {
|
||||||
assert_unsafe_precondition!(
|
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`",
|
"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::<T>(len)
|
data: *mut () = data as *mut (),
|
||||||
|
size: usize = size_of::<T>(),
|
||||||
|
align: usize = align_of::<T>(),
|
||||||
|
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)
|
&mut *ptr::slice_from_raw_parts_mut(data, len)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Rvalue::UnaryOp(_, operand) => {
|
Rvalue::UnaryOp(_, operand) => {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
|
||||||
const ENTRY_LIMIT: usize = 900;
|
const ENTRY_LIMIT: usize = 900;
|
||||||
// FIXME: The following limits should be reduced eventually.
|
// FIXME: The following limits should be reduced eventually.
|
||||||
const ISSUES_ENTRY_LIMIT: usize = 1819;
|
const ISSUES_ENTRY_LIMIT: usize = 1819;
|
||||||
const ROOT_ENTRY_LIMIT: usize = 871;
|
const ROOT_ENTRY_LIMIT: usize = 872;
|
||||||
|
|
||||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||||
"rs", // test source files
|
"rs", // test source files
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// only-x86_64
|
// only-x86_64
|
||||||
// ignore-sgx
|
// ignore-sgx
|
||||||
// revisions: opt-speed opt-size
|
// revisions: opt-speed opt-size
|
||||||
// [opt-speed] compile-flags: -Copt-level=1
|
// [opt-speed] compile-flags: -Copt-level=2 -Cdebug-assertions=no
|
||||||
// [opt-size] compile-flags: -Copt-level=s
|
// [opt-size] compile-flags: -Copt-level=s -Cdebug-assertions=no
|
||||||
#![crate_type="rlib"]
|
#![crate_type="rlib"]
|
||||||
|
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
|
|
@ -24,29 +24,11 @@
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
let mut _8: *const [bool; 0];
|
let mut _8: bool;
|
||||||
let mut _9: *mut [bool; 0];
|
let _9: ();
|
||||||
|
let mut _10: *mut ();
|
||||||
|
let mut _11: *const [bool; 0];
|
||||||
scope 12 {
|
scope 12 {
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
|
|
||||||
debug ptr => _9;
|
|
||||||
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
|
|
||||||
debug self => _9;
|
|
||||||
let mut _10: *mut u8;
|
|
||||||
scope 15 {
|
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _10;
|
|
||||||
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
|
||||||
debug self => _10;
|
|
||||||
scope 18 {
|
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +48,7 @@
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
|
StorageLive(_9);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
|
@ -73,30 +56,41 @@
|
||||||
_7 = const 1_usize;
|
_7 = const 1_usize;
|
||||||
_6 = const {0x1 as *mut [bool; 0]};
|
_6 = const {0x1 as *mut [bool; 0]};
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_8);
|
|
||||||
StorageLive(_9);
|
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
_8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_11);
|
||||||
_5 = NonNull::<[bool; 0]> { pointer: _8 };
|
StorageLive(_8);
|
||||||
StorageDead(_10);
|
_8 = cfg!(debug_assertions);
|
||||||
StorageDead(_9);
|
switchInt(move _8) -> [0: bb3, otherwise: bb2];
|
||||||
StorageDead(_8);
|
|
||||||
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(_3);
|
|
||||||
_1 = A { foo: move _2 };
|
|
||||||
StorageDead(_2);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_1) -> [return: bb1, unwind unreachable];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageDead(_1);
|
StorageDead(_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
|
||||||
|
_9 = NonNull::<T>::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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,29 +24,11 @@
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
let mut _8: *const [bool; 0];
|
let mut _8: bool;
|
||||||
let mut _9: *mut [bool; 0];
|
let _9: ();
|
||||||
|
let mut _10: *mut ();
|
||||||
|
let mut _11: *const [bool; 0];
|
||||||
scope 12 {
|
scope 12 {
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
|
|
||||||
debug ptr => _9;
|
|
||||||
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
|
|
||||||
debug self => _9;
|
|
||||||
let mut _10: *mut u8;
|
|
||||||
scope 15 {
|
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _10;
|
|
||||||
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
|
||||||
debug self => _10;
|
|
||||||
scope 18 {
|
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +48,7 @@
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
|
StorageLive(_9);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
|
@ -73,25 +56,11 @@
|
||||||
_7 = const 1_usize;
|
_7 = const 1_usize;
|
||||||
_6 = const {0x1 as *mut [bool; 0]};
|
_6 = const {0x1 as *mut [bool; 0]};
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_8);
|
|
||||||
StorageLive(_9);
|
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
_8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_11);
|
||||||
_5 = NonNull::<[bool; 0]> { pointer: _8 };
|
StorageLive(_8);
|
||||||
StorageDead(_10);
|
_8 = cfg!(debug_assertions);
|
||||||
StorageDead(_9);
|
switchInt(move _8) -> [0: bb4, otherwise: bb3];
|
||||||
StorageDead(_8);
|
|
||||||
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(_3);
|
|
||||||
_1 = A { foo: move _2 };
|
|
||||||
StorageDead(_2);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_1) -> [return: bb1, unwind: bb2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -102,5 +71,30 @@
|
||||||
bb2 (cleanup): {
|
bb2 (cleanup): {
|
||||||
resume;
|
resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
_10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
|
||||||
|
_9 = NonNull::<T>::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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,29 +24,11 @@
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
let mut _8: *const [bool; 0];
|
let mut _8: bool;
|
||||||
let mut _9: *mut [bool; 0];
|
let _9: ();
|
||||||
|
let mut _10: *mut ();
|
||||||
|
let mut _11: *const [bool; 0];
|
||||||
scope 12 {
|
scope 12 {
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
|
|
||||||
debug ptr => _9;
|
|
||||||
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
|
|
||||||
debug self => _9;
|
|
||||||
let mut _10: *mut u8;
|
|
||||||
scope 15 {
|
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _10;
|
|
||||||
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
|
||||||
debug self => _10;
|
|
||||||
scope 18 {
|
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +48,7 @@
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
|
StorageLive(_9);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
|
@ -73,30 +56,41 @@
|
||||||
_7 = const 1_usize;
|
_7 = const 1_usize;
|
||||||
_6 = const {0x1 as *mut [bool; 0]};
|
_6 = const {0x1 as *mut [bool; 0]};
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_8);
|
|
||||||
StorageLive(_9);
|
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
_8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_11);
|
||||||
_5 = NonNull::<[bool; 0]> { pointer: _8 };
|
StorageLive(_8);
|
||||||
StorageDead(_10);
|
_8 = cfg!(debug_assertions);
|
||||||
StorageDead(_9);
|
switchInt(move _8) -> [0: bb3, otherwise: bb2];
|
||||||
StorageDead(_8);
|
|
||||||
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(_3);
|
|
||||||
_1 = A { foo: move _2 };
|
|
||||||
StorageDead(_2);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_1) -> [return: bb1, unwind unreachable];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageDead(_1);
|
StorageDead(_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
|
||||||
|
_9 = NonNull::<T>::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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,29 +24,11 @@
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
let mut _8: *const [bool; 0];
|
let mut _8: bool;
|
||||||
let mut _9: *mut [bool; 0];
|
let _9: ();
|
||||||
|
let mut _10: *mut ();
|
||||||
|
let mut _11: *const [bool; 0];
|
||||||
scope 12 {
|
scope 12 {
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
|
|
||||||
debug ptr => _9;
|
|
||||||
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
|
|
||||||
debug self => _9;
|
|
||||||
let mut _10: *mut u8;
|
|
||||||
scope 15 {
|
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _10;
|
|
||||||
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
|
||||||
debug self => _10;
|
|
||||||
scope 18 {
|
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +48,7 @@
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
|
StorageLive(_9);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
|
@ -73,25 +56,11 @@
|
||||||
_7 = const 1_usize;
|
_7 = const 1_usize;
|
||||||
_6 = const {0x1 as *mut [bool; 0]};
|
_6 = const {0x1 as *mut [bool; 0]};
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_8);
|
|
||||||
StorageLive(_9);
|
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
_8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_11);
|
||||||
_5 = NonNull::<[bool; 0]> { pointer: _8 };
|
StorageLive(_8);
|
||||||
StorageDead(_10);
|
_8 = cfg!(debug_assertions);
|
||||||
StorageDead(_9);
|
switchInt(move _8) -> [0: bb4, otherwise: bb3];
|
||||||
StorageDead(_8);
|
|
||||||
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(_3);
|
|
||||||
_1 = A { foo: move _2 };
|
|
||||||
StorageDead(_2);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_1) -> [return: bb1, unwind: bb2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -102,5 +71,30 @@
|
||||||
bb2 (cleanup): {
|
bb2 (cleanup): {
|
||||||
resume;
|
resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
_10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
|
||||||
|
_9 = NonNull::<T>::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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,29 +24,11 @@
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
let mut _8: *const [bool; 0];
|
let mut _8: bool;
|
||||||
let mut _9: *mut [bool; 0];
|
let _9: ();
|
||||||
|
let mut _10: *mut ();
|
||||||
|
let mut _11: *const [bool; 0];
|
||||||
scope 12 {
|
scope 12 {
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
|
|
||||||
debug ptr => _9;
|
|
||||||
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
|
|
||||||
debug self => _9;
|
|
||||||
let mut _10: *mut u8;
|
|
||||||
scope 15 {
|
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _10;
|
|
||||||
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
|
||||||
debug self => _10;
|
|
||||||
scope 18 {
|
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +48,7 @@
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
|
StorageLive(_9);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
|
@ -75,31 +58,43 @@
|
||||||
+ _7 = const 1_usize;
|
+ _7 = const 1_usize;
|
||||||
+ _6 = const {0x1 as *mut [bool; 0]};
|
+ _6 = const {0x1 as *mut [bool; 0]};
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_8);
|
|
||||||
StorageLive(_9);
|
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_11);
|
||||||
+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_8);
|
||||||
_5 = NonNull::<[bool; 0]> { pointer: _8 };
|
_8 = cfg!(debug_assertions);
|
||||||
StorageDead(_10);
|
switchInt(move _8) -> [0: bb3, otherwise: bb2];
|
||||||
StorageDead(_9);
|
|
||||||
StorageDead(_8);
|
|
||||||
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(_3);
|
|
||||||
_1 = A { foo: move _2 };
|
|
||||||
StorageDead(_2);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_1) -> [return: bb1, unwind unreachable];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageDead(_1);
|
StorageDead(_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
- _10 = _6 as *mut () (PtrToPtr);
|
||||||
|
+ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
|
||||||
|
_9 = NonNull::<T>::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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,29 +24,11 @@
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
let mut _8: *const [bool; 0];
|
let mut _8: bool;
|
||||||
let mut _9: *mut [bool; 0];
|
let _9: ();
|
||||||
|
let mut _10: *mut ();
|
||||||
|
let mut _11: *const [bool; 0];
|
||||||
scope 12 {
|
scope 12 {
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
|
|
||||||
debug ptr => _9;
|
|
||||||
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
|
|
||||||
debug self => _9;
|
|
||||||
let mut _10: *mut u8;
|
|
||||||
scope 15 {
|
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _10;
|
|
||||||
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
|
||||||
debug self => _10;
|
|
||||||
scope 18 {
|
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +48,7 @@
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
|
StorageLive(_9);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
|
@ -75,26 +58,11 @@
|
||||||
+ _7 = const 1_usize;
|
+ _7 = const 1_usize;
|
||||||
+ _6 = const {0x1 as *mut [bool; 0]};
|
+ _6 = const {0x1 as *mut [bool; 0]};
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_8);
|
|
||||||
StorageLive(_9);
|
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_11);
|
||||||
+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_8);
|
||||||
_5 = NonNull::<[bool; 0]> { pointer: _8 };
|
_8 = cfg!(debug_assertions);
|
||||||
StorageDead(_10);
|
switchInt(move _8) -> [0: bb4, otherwise: bb3];
|
||||||
StorageDead(_9);
|
|
||||||
StorageDead(_8);
|
|
||||||
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(_3);
|
|
||||||
_1 = A { foo: move _2 };
|
|
||||||
StorageDead(_2);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_1) -> [return: bb1, unwind: bb2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -105,5 +73,32 @@
|
||||||
bb2 (cleanup): {
|
bb2 (cleanup): {
|
||||||
resume;
|
resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
- _10 = _6 as *mut () (PtrToPtr);
|
||||||
|
+ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
|
||||||
|
_9 = NonNull::<T>::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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,29 +24,11 @@
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
let mut _8: *const [bool; 0];
|
let mut _8: bool;
|
||||||
let mut _9: *mut [bool; 0];
|
let _9: ();
|
||||||
|
let mut _10: *mut ();
|
||||||
|
let mut _11: *const [bool; 0];
|
||||||
scope 12 {
|
scope 12 {
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
|
|
||||||
debug ptr => _9;
|
|
||||||
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
|
|
||||||
debug self => _9;
|
|
||||||
let mut _10: *mut u8;
|
|
||||||
scope 15 {
|
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _10;
|
|
||||||
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
|
||||||
debug self => _10;
|
|
||||||
scope 18 {
|
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +48,7 @@
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
|
StorageLive(_9);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
|
@ -75,31 +58,43 @@
|
||||||
+ _7 = const 1_usize;
|
+ _7 = const 1_usize;
|
||||||
+ _6 = const {0x1 as *mut [bool; 0]};
|
+ _6 = const {0x1 as *mut [bool; 0]};
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_8);
|
|
||||||
StorageLive(_9);
|
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_11);
|
||||||
+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_8);
|
||||||
_5 = NonNull::<[bool; 0]> { pointer: _8 };
|
_8 = cfg!(debug_assertions);
|
||||||
StorageDead(_10);
|
switchInt(move _8) -> [0: bb3, otherwise: bb2];
|
||||||
StorageDead(_9);
|
|
||||||
StorageDead(_8);
|
|
||||||
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(_3);
|
|
||||||
_1 = A { foo: move _2 };
|
|
||||||
StorageDead(_2);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_1) -> [return: bb1, unwind unreachable];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageDead(_1);
|
StorageDead(_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
- _10 = _6 as *mut () (PtrToPtr);
|
||||||
|
+ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
|
||||||
|
_9 = NonNull::<T>::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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,29 +24,11 @@
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
|
||||||
debug ptr => _6;
|
debug ptr => _6;
|
||||||
let mut _8: *const [bool; 0];
|
let mut _8: bool;
|
||||||
let mut _9: *mut [bool; 0];
|
let _9: ();
|
||||||
|
let mut _10: *mut ();
|
||||||
|
let mut _11: *const [bool; 0];
|
||||||
scope 12 {
|
scope 12 {
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
|
|
||||||
debug ptr => _9;
|
|
||||||
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
|
|
||||||
debug self => _9;
|
|
||||||
let mut _10: *mut u8;
|
|
||||||
scope 15 {
|
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _10;
|
|
||||||
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
|
||||||
debug self => _10;
|
|
||||||
scope 18 {
|
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +48,7 @@
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
|
StorageLive(_9);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
|
@ -75,26 +58,11 @@
|
||||||
+ _7 = const 1_usize;
|
+ _7 = const 1_usize;
|
||||||
+ _6 = const {0x1 as *mut [bool; 0]};
|
+ _6 = const {0x1 as *mut [bool; 0]};
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_8);
|
|
||||||
StorageLive(_9);
|
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_11);
|
||||||
+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
|
StorageLive(_8);
|
||||||
_5 = NonNull::<[bool; 0]> { pointer: _8 };
|
_8 = cfg!(debug_assertions);
|
||||||
StorageDead(_10);
|
switchInt(move _8) -> [0: bb4, otherwise: bb3];
|
||||||
StorageDead(_9);
|
|
||||||
StorageDead(_8);
|
|
||||||
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(_3);
|
|
||||||
_1 = A { foo: move _2 };
|
|
||||||
StorageDead(_2);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_1) -> [return: bb1, unwind: bb2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -105,5 +73,32 @@
|
||||||
bb2 (cleanup): {
|
bb2 (cleanup): {
|
||||||
resume;
|
resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
- _10 = _6 as *mut () (PtrToPtr);
|
||||||
|
+ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
|
||||||
|
_9 = NonNull::<T>::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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||||
// ignore-debug: the debug assertions prevent the inlining we are testing for
|
// 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.Inline.diff
|
||||||
// EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
|
// EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
|
||||||
|
|
|
@ -7,41 +7,44 @@
|
||||||
let mut _2: std::option::Option<T>;
|
let mut _2: std::option::Option<T>;
|
||||||
+ scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
|
+ scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
|
||||||
+ debug self => _2;
|
+ debug self => _2;
|
||||||
+ let mut _3: &std::option::Option<T>;
|
+ let mut _3: isize;
|
||||||
+ let mut _4: isize;
|
|
||||||
+ let mut _5: bool;
|
|
||||||
+ scope 2 {
|
+ scope 2 {
|
||||||
+ debug val => _0;
|
+ debug val => _0;
|
||||||
+ }
|
+ }
|
||||||
+ scope 3 {
|
+ scope 3 {
|
||||||
+ scope 5 (inlined unreachable_unchecked) {
|
+ scope 4 (inlined unreachable_unchecked) {
|
||||||
+ scope 6 {
|
+ let mut _4: bool;
|
||||||
+ scope 7 (inlined unreachable_unchecked::runtime) {
|
+ let _5: ();
|
||||||
+ }
|
+ scope 5 {
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ scope 4 (inlined Option::<T>::is_some) {
|
|
||||||
+ debug self => _3;
|
|
||||||
+ }
|
|
||||||
+ }
|
+ }
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
_2 = move _1;
|
_2 = move _1;
|
||||||
- _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
|
- _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
|
||||||
- }
|
|
||||||
-
|
|
||||||
- bb1: {
|
|
||||||
+ StorageLive(_3);
|
+ StorageLive(_3);
|
||||||
+ StorageLive(_4);
|
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ _4 = discriminant(_2);
|
+ _3 = discriminant(_2);
|
||||||
+ _5 = Eq(_4, const 1_isize);
|
+ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2];
|
||||||
+ assume(move _5);
|
}
|
||||||
|
|
||||||
|
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);
|
+ _0 = move ((_2 as Some).0: T);
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
+ StorageDead(_4);
|
|
||||||
+ StorageDead(_3);
|
+ StorageDead(_3);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -7,48 +7,51 @@
|
||||||
let mut _2: std::option::Option<T>;
|
let mut _2: std::option::Option<T>;
|
||||||
+ scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
|
+ scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
|
||||||
+ debug self => _2;
|
+ debug self => _2;
|
||||||
+ let mut _3: &std::option::Option<T>;
|
+ let mut _3: isize;
|
||||||
+ let mut _4: isize;
|
|
||||||
+ let mut _5: bool;
|
|
||||||
+ scope 2 {
|
+ scope 2 {
|
||||||
+ debug val => _0;
|
+ debug val => _0;
|
||||||
+ }
|
+ }
|
||||||
+ scope 3 {
|
+ scope 3 {
|
||||||
+ scope 5 (inlined unreachable_unchecked) {
|
+ scope 4 (inlined unreachable_unchecked) {
|
||||||
+ scope 6 {
|
+ let mut _4: bool;
|
||||||
+ scope 7 (inlined unreachable_unchecked::runtime) {
|
+ let _5: ();
|
||||||
+ }
|
+ scope 5 {
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ scope 4 (inlined Option::<T>::is_some) {
|
|
||||||
+ debug self => _3;
|
|
||||||
+ }
|
|
||||||
+ }
|
+ }
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
_2 = move _1;
|
_2 = move _1;
|
||||||
- _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
|
- _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
|
||||||
- }
|
|
||||||
-
|
|
||||||
- bb1: {
|
|
||||||
+ StorageLive(_3);
|
+ StorageLive(_3);
|
||||||
+ StorageLive(_4);
|
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ _4 = discriminant(_2);
|
+ _3 = discriminant(_2);
|
||||||
+ _5 = Eq(_4, const 1_isize);
|
+ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2];
|
||||||
+ assume(move _5);
|
}
|
||||||
+ _0 = move ((_2 as Some).0: T);
|
|
||||||
+ StorageDead(_5);
|
bb1: {
|
||||||
+ StorageDead(_4);
|
- StorageDead(_2);
|
||||||
+ StorageDead(_3);
|
- return;
|
||||||
StorageDead(_2);
|
+ StorageLive(_4);
|
||||||
return;
|
+ _4 = cfg!(debug_assertions);
|
||||||
- }
|
+ assume(_4);
|
||||||
-
|
+ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
- bb2 (cleanup): {
|
- bb2 (cleanup): {
|
||||||
- resume;
|
- resume;
|
||||||
|
+ bb2: {
|
||||||
|
+ unreachable;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb3: {
|
||||||
|
+ _0 = move ((_2 as Some).0: T);
|
||||||
|
+ StorageDead(_5);
|
||||||
|
+ StorageDead(_3);
|
||||||
|
+ StorageDead(_2);
|
||||||
|
+ return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
|
||||||
scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
|
scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
let mut _2: isize;
|
let mut _2: isize;
|
||||||
let mut _3: bool;
|
|
||||||
let mut _4: &std::option::Option<T>;
|
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug val => _0;
|
debug val => _0;
|
||||||
}
|
}
|
||||||
scope 3 {
|
scope 3 {
|
||||||
scope 5 (inlined unreachable_unchecked) {
|
scope 4 (inlined unreachable_unchecked) {
|
||||||
scope 6 {
|
let mut _3: bool;
|
||||||
scope 7 (inlined unreachable_unchecked::runtime) {
|
let _4: ();
|
||||||
}
|
scope 5 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 4 (inlined Option::<T>::is_some) {
|
|
||||||
debug self => _4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_4);
|
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
|
||||||
_2 = discriminant(_1);
|
_2 = discriminant(_1);
|
||||||
_3 = Eq(_2, const 1_isize);
|
switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3];
|
||||||
assume(move _3);
|
}
|
||||||
|
|
||||||
|
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);
|
_0 = ((_1 as Some).0: T);
|
||||||
StorageDead(_3);
|
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
StorageDead(_4);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
|
||||||
scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
|
scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
let mut _2: isize;
|
let mut _2: isize;
|
||||||
let mut _3: bool;
|
|
||||||
let mut _4: &std::option::Option<T>;
|
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug val => _0;
|
debug val => _0;
|
||||||
}
|
}
|
||||||
scope 3 {
|
scope 3 {
|
||||||
scope 5 (inlined unreachable_unchecked) {
|
scope 4 (inlined unreachable_unchecked) {
|
||||||
scope 6 {
|
let mut _3: bool;
|
||||||
scope 7 (inlined unreachable_unchecked::runtime) {
|
let _4: ();
|
||||||
}
|
scope 5 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 4 (inlined Option::<T>::is_some) {
|
|
||||||
debug self => _4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_4);
|
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
StorageLive(_3);
|
|
||||||
_2 = discriminant(_1);
|
_2 = discriminant(_1);
|
||||||
_3 = Eq(_2, const 1_isize);
|
switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3];
|
||||||
assume(move _3);
|
}
|
||||||
|
|
||||||
|
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);
|
_0 = ((_1 as Some).0: T);
|
||||||
StorageDead(_3);
|
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
StorageDead(_4);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,31 @@ fn ub_if_b(_1: Thing) -> Thing {
|
||||||
debug t => _1;
|
debug t => _1;
|
||||||
let mut _0: Thing;
|
let mut _0: Thing;
|
||||||
let mut _2: isize;
|
let mut _2: isize;
|
||||||
let mut _3: bool;
|
|
||||||
scope 1 (inlined unreachable_unchecked) {
|
scope 1 (inlined unreachable_unchecked) {
|
||||||
|
let mut _3: bool;
|
||||||
|
let _4: ();
|
||||||
scope 2 {
|
scope 2 {
|
||||||
scope 3 (inlined unreachable_unchecked::runtime) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
_2 = discriminant(_1);
|
_2 = discriminant(_1);
|
||||||
_3 = Eq(_2, const 0_isize);
|
switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3];
|
||||||
assume(move _3);
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
_0 = move _1;
|
_0 = move _1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageLive(_3);
|
||||||
|
_3 = cfg!(debug_assertions);
|
||||||
|
assume(_3);
|
||||||
|
_4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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::<u32>) {
|
|
||||||
debug dest => _1;
|
|
||||||
debug src => _2;
|
|
||||||
scope 2 {
|
|
||||||
scope 3 {
|
|
||||||
debug result => _0;
|
|
||||||
scope 16 (inlined std::ptr::write::<u32>) {
|
|
||||||
debug dst => _1;
|
|
||||||
debug src => _2;
|
|
||||||
scope 17 {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scope 4 (inlined std::ptr::read::<u32>) {
|
|
||||||
debug src => _1;
|
|
||||||
let mut _3: *const u32;
|
|
||||||
scope 5 {
|
|
||||||
scope 6 (inlined std::ptr::read::runtime::<u32>) {
|
|
||||||
debug src => _3;
|
|
||||||
scope 7 (inlined intrinsics::is_aligned_and_not_null::<u32>) {
|
|
||||||
debug ptr => _3;
|
|
||||||
scope 8 (inlined std::ptr::const_ptr::<impl *const u32>::is_null) {
|
|
||||||
debug self => _3;
|
|
||||||
let mut _4: *const u8;
|
|
||||||
scope 9 {
|
|
||||||
scope 10 (inlined std::ptr::const_ptr::<impl *const T>::is_null::runtime_impl) {
|
|
||||||
debug ptr => _4;
|
|
||||||
scope 11 (inlined std::ptr::const_ptr::<impl *const u8>::addr) {
|
|
||||||
debug self => _4;
|
|
||||||
scope 12 {
|
|
||||||
scope 13 (inlined std::ptr::const_ptr::<impl *const u8>::cast::<()>) {
|
|
||||||
debug self => _4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scope 14 (inlined std::ptr::const_ptr::<impl *const u32>::is_aligned) {
|
|
||||||
debug self => _3;
|
|
||||||
scope 15 (inlined align_of::<u32>) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bb0: {
|
|
||||||
StorageLive(_3);
|
|
||||||
StorageLive(_4);
|
|
||||||
_0 = (*_1);
|
|
||||||
StorageDead(_4);
|
|
||||||
StorageDead(_3);
|
|
||||||
(*_1) = _2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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::<u32>) {
|
||||||
|
debug dest => _1;
|
||||||
|
debug src => _2;
|
||||||
|
scope 2 {
|
||||||
|
scope 3 {
|
||||||
|
debug result => _0;
|
||||||
|
scope 6 (inlined std::ptr::write::<u32>) {
|
||||||
|
debug dst => _1;
|
||||||
|
debug src => _2;
|
||||||
|
scope 7 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scope 4 (inlined std::ptr::read::<u32>) {
|
||||||
|
debug src => _1;
|
||||||
|
scope 5 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
_0 = (*_1);
|
||||||
|
(*_1) = _2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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::<u32>) {
|
||||||
|
debug dest => _1;
|
||||||
|
debug src => _2;
|
||||||
|
scope 2 {
|
||||||
|
scope 3 {
|
||||||
|
debug result => _0;
|
||||||
|
scope 6 (inlined std::ptr::write::<u32>) {
|
||||||
|
debug dst => _1;
|
||||||
|
debug src => _2;
|
||||||
|
scope 7 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scope 4 (inlined std::ptr::read::<u32>) {
|
||||||
|
debug src => _1;
|
||||||
|
scope 5 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
_0 = (*_1);
|
||||||
|
(*_1) = _2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
// skip-filecheck
|
// 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
|
// only-64bit
|
||||||
// ignore-debug the standard library debug assertions leak into this test
|
// ignore-debug the standard library debug assertions leak into this test
|
||||||
|
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
|
|
@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
debug f => _2;
|
debug f => _2;
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
let mut _13: std::slice::Iter<'_, T>;
|
let mut _15: std::slice::Iter<'_, T>;
|
||||||
let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
let mut _16: std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
||||||
let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
let mut _17: std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
||||||
let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
let mut _18: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
||||||
let mut _17: std::option::Option<(usize, &T)>;
|
let mut _19: std::option::Option<(usize, &T)>;
|
||||||
let mut _18: isize;
|
let mut _20: isize;
|
||||||
let mut _21: &impl Fn(usize, &T);
|
let mut _23: &impl Fn(usize, &T);
|
||||||
let mut _22: (usize, &T);
|
let mut _24: (usize, &T);
|
||||||
let _23: ();
|
let _25: ();
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug iter => _15;
|
debug iter => _17;
|
||||||
let _19: usize;
|
let _21: usize;
|
||||||
let _20: &T;
|
let _22: &T;
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug i => _19;
|
debug i => _21;
|
||||||
debug x => _20;
|
debug x => _22;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
let _4: *const T;
|
let _3: usize;
|
||||||
let mut _5: bool;
|
let mut _5: std::ptr::NonNull<[T]>;
|
||||||
let mut _6: usize;
|
let mut _10: bool;
|
||||||
let mut _8: usize;
|
let mut _11: *mut T;
|
||||||
let mut _9: *mut T;
|
let mut _12: *mut T;
|
||||||
let mut _11: std::ptr::NonNull<T>;
|
let mut _14: *const T;
|
||||||
let mut _12: *const T;
|
|
||||||
scope 5 {
|
scope 5 {
|
||||||
debug ptr => _4;
|
debug len => _3;
|
||||||
|
let _9: std::ptr::NonNull<T>;
|
||||||
scope 6 {
|
scope 6 {
|
||||||
let _7: *const T;
|
debug ptr => _9;
|
||||||
scope 7 {
|
scope 7 {
|
||||||
debug end_or_len => _7;
|
let _13: *const T;
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked) {
|
scope 8 {
|
||||||
debug ptr => _9;
|
debug end_or_len => _13;
|
||||||
let mut _10: *const T;
|
}
|
||||||
let mut _24: *mut T;
|
scope 14 (inlined invalid::<T>) {
|
||||||
scope 14 {
|
debug addr => _3;
|
||||||
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
|
scope 15 {
|
||||||
debug ptr => _24;
|
}
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
|
}
|
||||||
debug self => _24;
|
scope 16 (inlined NonNull::<T>::as_ptr) {
|
||||||
let mut _25: *mut u8;
|
debug self => _9;
|
||||||
scope 17 {
|
}
|
||||||
scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
|
||||||
debug ptr => _25;
|
debug self => _11;
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
debug count => _3;
|
||||||
debug self => _25;
|
scope 18 {
|
||||||
scope 20 {
|
|
||||||
scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 9 (inlined invalid::<T>) {
|
}
|
||||||
debug addr => _8;
|
scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
|
||||||
scope 10 {
|
debug reference => _1;
|
||||||
}
|
let mut _4: *const [T];
|
||||||
|
scope 10 {
|
||||||
}
|
}
|
||||||
scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
|
}
|
||||||
debug self => _4;
|
scope 11 (inlined NonNull::<[T]>::cast::<T>) {
|
||||||
debug count => _6;
|
debug self => _5;
|
||||||
scope 12 {
|
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::<impl [T]>::as_ptr) {
|
|
||||||
debug self => _1;
|
|
||||||
let mut _3: *const [T];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
|
scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
|
||||||
debug self => _13;
|
debug self => _15;
|
||||||
scope 23 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
|
scope 20 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
|
||||||
debug iter => _13;
|
debug iter => _15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 24 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
|
scope 21 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
|
||||||
debug self => _14;
|
debug self => _16;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_13);
|
StorageLive(_15);
|
||||||
StorageLive(_4);
|
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = &raw const (*_1);
|
StorageLive(_9);
|
||||||
_4 = move _3 as *const T (PtrToPtr);
|
StorageLive(_4);
|
||||||
StorageDead(_3);
|
StorageLive(_8);
|
||||||
StorageLive(_7);
|
_3 = Len((*_1));
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = const _;
|
_4 = &raw const (*_1);
|
||||||
switchInt(move _5) -> [0: bb1, otherwise: bb2];
|
_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::<T> { pointer: _8 };
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_13);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = const _;
|
||||||
|
switchInt(move _10) -> [0: bb1, otherwise: bb2];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_6);
|
StorageLive(_12);
|
||||||
_6 = Len((*_1));
|
StorageLive(_11);
|
||||||
_7 = Offset(_4, _6);
|
_11 = _8 as *mut T (PtrToPtr);
|
||||||
StorageDead(_6);
|
_12 = Offset(_11, _3);
|
||||||
|
StorageDead(_11);
|
||||||
|
_13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
|
||||||
|
StorageDead(_12);
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageLive(_8);
|
_13 = _3 as *const T (Transmute);
|
||||||
_8 = Len((*_1));
|
|
||||||
_7 = _8 as *const T (Transmute);
|
|
||||||
StorageDead(_8);
|
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
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::<T> { pointer: _10 };
|
|
||||||
StorageDead(_25);
|
|
||||||
StorageDead(_24);
|
|
||||||
StorageDead(_10);
|
StorageDead(_10);
|
||||||
StorageDead(_9);
|
StorageLive(_14);
|
||||||
StorageLive(_12);
|
_14 = _13;
|
||||||
_12 = _7;
|
_15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
|
||||||
_13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
|
StorageDead(_14);
|
||||||
StorageDead(_12);
|
|
||||||
StorageDead(_11);
|
|
||||||
StorageDead(_7);
|
|
||||||
StorageDead(_4);
|
|
||||||
_14 = Enumerate::<std::slice::Iter<'_, T>> { iter: _13, count: const 0_usize };
|
|
||||||
StorageDead(_13);
|
StorageDead(_13);
|
||||||
StorageLive(_15);
|
StorageDead(_8);
|
||||||
_15 = _14;
|
StorageDead(_4);
|
||||||
|
StorageDead(_9);
|
||||||
|
StorageDead(_3);
|
||||||
|
_16 = Enumerate::<std::slice::Iter<'_, T>> { iter: _15, count: const 0_usize };
|
||||||
|
StorageDead(_15);
|
||||||
|
StorageLive(_17);
|
||||||
|
_17 = _16;
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
StorageLive(_17);
|
StorageLive(_19);
|
||||||
StorageLive(_16);
|
StorageLive(_18);
|
||||||
_16 = &mut _15;
|
_18 = &mut _17;
|
||||||
_17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind unreachable];
|
_19 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _18) -> [return: bb5, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
StorageDead(_16);
|
StorageDead(_18);
|
||||||
_18 = discriminant(_17);
|
_20 = discriminant(_19);
|
||||||
switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
|
switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
|
StorageDead(_19);
|
||||||
StorageDead(_17);
|
StorageDead(_17);
|
||||||
StorageDead(_15);
|
|
||||||
drop(_2) -> [return: bb7, unwind unreachable];
|
drop(_2) -> [return: bb7, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8: {
|
bb8: {
|
||||||
_19 = (((_17 as Some).0: (usize, &T)).0: usize);
|
_21 = (((_19 as Some).0: (usize, &T)).0: usize);
|
||||||
_20 = (((_17 as Some).0: (usize, &T)).1: &T);
|
_22 = (((_19 as Some).0: (usize, &T)).1: &T);
|
||||||
StorageLive(_21);
|
StorageLive(_23);
|
||||||
_21 = &_2;
|
_23 = &_2;
|
||||||
StorageLive(_22);
|
StorageLive(_24);
|
||||||
_22 = (_19, _20);
|
_24 = (_21, _22);
|
||||||
_23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable];
|
_25 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _23, move _24) -> [return: bb9, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageDead(_22);
|
StorageDead(_24);
|
||||||
StorageDead(_21);
|
StorageDead(_23);
|
||||||
StorageDead(_17);
|
StorageDead(_19);
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
debug f => _2;
|
debug f => _2;
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
let mut _13: std::slice::Iter<'_, T>;
|
let mut _15: std::slice::Iter<'_, T>;
|
||||||
let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
let mut _16: std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
||||||
let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
let mut _17: std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
||||||
let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
let mut _18: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
|
||||||
let mut _17: std::option::Option<(usize, &T)>;
|
let mut _19: std::option::Option<(usize, &T)>;
|
||||||
let mut _18: isize;
|
let mut _20: isize;
|
||||||
let mut _21: &impl Fn(usize, &T);
|
let mut _23: &impl Fn(usize, &T);
|
||||||
let mut _22: (usize, &T);
|
let mut _24: (usize, &T);
|
||||||
let _23: ();
|
let _25: ();
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug iter => _15;
|
debug iter => _17;
|
||||||
let _19: usize;
|
let _21: usize;
|
||||||
let _20: &T;
|
let _22: &T;
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug i => _19;
|
debug i => _21;
|
||||||
debug x => _20;
|
debug x => _22;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
let _4: *const T;
|
let _3: usize;
|
||||||
let mut _5: bool;
|
let mut _5: std::ptr::NonNull<[T]>;
|
||||||
let mut _6: usize;
|
let mut _10: bool;
|
||||||
let mut _8: usize;
|
let mut _11: *mut T;
|
||||||
let mut _9: *mut T;
|
let mut _12: *mut T;
|
||||||
let mut _11: std::ptr::NonNull<T>;
|
let mut _14: *const T;
|
||||||
let mut _12: *const T;
|
|
||||||
scope 5 {
|
scope 5 {
|
||||||
debug ptr => _4;
|
debug len => _3;
|
||||||
|
let _9: std::ptr::NonNull<T>;
|
||||||
scope 6 {
|
scope 6 {
|
||||||
let _7: *const T;
|
debug ptr => _9;
|
||||||
scope 7 {
|
scope 7 {
|
||||||
debug end_or_len => _7;
|
let _13: *const T;
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked) {
|
scope 8 {
|
||||||
debug ptr => _9;
|
debug end_or_len => _13;
|
||||||
let mut _10: *const T;
|
}
|
||||||
let mut _24: *mut T;
|
scope 14 (inlined invalid::<T>) {
|
||||||
scope 14 {
|
debug addr => _3;
|
||||||
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
|
scope 15 {
|
||||||
debug ptr => _24;
|
}
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
|
}
|
||||||
debug self => _24;
|
scope 16 (inlined NonNull::<T>::as_ptr) {
|
||||||
let mut _25: *mut u8;
|
debug self => _9;
|
||||||
scope 17 {
|
}
|
||||||
scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
|
||||||
debug ptr => _25;
|
debug self => _11;
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
debug count => _3;
|
||||||
debug self => _25;
|
scope 18 {
|
||||||
scope 20 {
|
|
||||||
scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 9 (inlined invalid::<T>) {
|
}
|
||||||
debug addr => _8;
|
scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
|
||||||
scope 10 {
|
debug reference => _1;
|
||||||
}
|
let mut _4: *const [T];
|
||||||
|
scope 10 {
|
||||||
}
|
}
|
||||||
scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
|
}
|
||||||
debug self => _4;
|
scope 11 (inlined NonNull::<[T]>::cast::<T>) {
|
||||||
debug count => _6;
|
debug self => _5;
|
||||||
scope 12 {
|
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::<impl [T]>::as_ptr) {
|
|
||||||
debug self => _1;
|
|
||||||
let mut _3: *const [T];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
|
scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
|
||||||
debug self => _13;
|
debug self => _15;
|
||||||
scope 23 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
|
scope 20 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
|
||||||
debug iter => _13;
|
debug iter => _15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 24 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
|
scope 21 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
|
||||||
debug self => _14;
|
debug self => _16;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_13);
|
StorageLive(_15);
|
||||||
StorageLive(_4);
|
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = &raw const (*_1);
|
StorageLive(_9);
|
||||||
_4 = move _3 as *const T (PtrToPtr);
|
StorageLive(_4);
|
||||||
StorageDead(_3);
|
StorageLive(_8);
|
||||||
StorageLive(_7);
|
_3 = Len((*_1));
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = const _;
|
_4 = &raw const (*_1);
|
||||||
switchInt(move _5) -> [0: bb1, otherwise: bb2];
|
_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::<T> { pointer: _8 };
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_13);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = const _;
|
||||||
|
switchInt(move _10) -> [0: bb1, otherwise: bb2];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_6);
|
StorageLive(_12);
|
||||||
_6 = Len((*_1));
|
StorageLive(_11);
|
||||||
_7 = Offset(_4, _6);
|
_11 = _8 as *mut T (PtrToPtr);
|
||||||
StorageDead(_6);
|
_12 = Offset(_11, _3);
|
||||||
|
StorageDead(_11);
|
||||||
|
_13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
|
||||||
|
StorageDead(_12);
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageLive(_8);
|
_13 = _3 as *const T (Transmute);
|
||||||
_8 = Len((*_1));
|
|
||||||
_7 = _8 as *const T (Transmute);
|
|
||||||
StorageDead(_8);
|
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
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::<T> { pointer: _10 };
|
|
||||||
StorageDead(_25);
|
|
||||||
StorageDead(_24);
|
|
||||||
StorageDead(_10);
|
StorageDead(_10);
|
||||||
StorageDead(_9);
|
StorageLive(_14);
|
||||||
StorageLive(_12);
|
_14 = _13;
|
||||||
_12 = _7;
|
_15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
|
||||||
_13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
|
StorageDead(_14);
|
||||||
StorageDead(_12);
|
|
||||||
StorageDead(_11);
|
|
||||||
StorageDead(_7);
|
|
||||||
StorageDead(_4);
|
|
||||||
_14 = Enumerate::<std::slice::Iter<'_, T>> { iter: _13, count: const 0_usize };
|
|
||||||
StorageDead(_13);
|
StorageDead(_13);
|
||||||
StorageLive(_15);
|
StorageDead(_8);
|
||||||
_15 = _14;
|
StorageDead(_4);
|
||||||
|
StorageDead(_9);
|
||||||
|
StorageDead(_3);
|
||||||
|
_16 = Enumerate::<std::slice::Iter<'_, T>> { iter: _15, count: const 0_usize };
|
||||||
|
StorageDead(_15);
|
||||||
|
StorageLive(_17);
|
||||||
|
_17 = _16;
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
StorageLive(_17);
|
StorageLive(_19);
|
||||||
StorageLive(_16);
|
StorageLive(_18);
|
||||||
_16 = &mut _15;
|
_18 = &mut _17;
|
||||||
_17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind: bb11];
|
_19 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _18) -> [return: bb5, unwind: bb11];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
StorageDead(_16);
|
StorageDead(_18);
|
||||||
_18 = discriminant(_17);
|
_20 = discriminant(_19);
|
||||||
switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
|
switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
|
StorageDead(_19);
|
||||||
StorageDead(_17);
|
StorageDead(_17);
|
||||||
StorageDead(_15);
|
|
||||||
drop(_2) -> [return: bb7, unwind continue];
|
drop(_2) -> [return: bb7, unwind continue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8: {
|
bb8: {
|
||||||
_19 = (((_17 as Some).0: (usize, &T)).0: usize);
|
_21 = (((_19 as Some).0: (usize, &T)).0: usize);
|
||||||
_20 = (((_17 as Some).0: (usize, &T)).1: &T);
|
_22 = (((_19 as Some).0: (usize, &T)).1: &T);
|
||||||
StorageLive(_21);
|
StorageLive(_23);
|
||||||
_21 = &_2;
|
_23 = &_2;
|
||||||
StorageLive(_22);
|
StorageLive(_24);
|
||||||
_22 = (_19, _20);
|
_24 = (_21, _22);
|
||||||
_23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11];
|
_25 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _23, move _24) -> [return: bb9, unwind: bb11];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageDead(_22);
|
StorageDead(_24);
|
||||||
StorageDead(_21);
|
StorageDead(_23);
|
||||||
StorageDead(_17);
|
StorageDead(_19);
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
debug f => _2;
|
debug f => _2;
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
let mut _13: std::slice::Iter<'_, T>;
|
let mut _15: std::slice::Iter<'_, T>;
|
||||||
let mut _14: std::slice::Iter<'_, T>;
|
let mut _16: std::slice::Iter<'_, T>;
|
||||||
let mut _15: &mut std::slice::Iter<'_, T>;
|
let mut _17: &mut std::slice::Iter<'_, T>;
|
||||||
let mut _16: std::option::Option<&T>;
|
let mut _18: std::option::Option<&T>;
|
||||||
let mut _17: isize;
|
let mut _19: isize;
|
||||||
let mut _19: &impl Fn(&T);
|
let mut _21: &impl Fn(&T);
|
||||||
let mut _20: (&T,);
|
let mut _22: (&T,);
|
||||||
let _21: ();
|
let _23: ();
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug iter => _14;
|
debug iter => _16;
|
||||||
let _18: &T;
|
let _20: &T;
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug x => _18;
|
debug x => _20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
let _4: *const T;
|
let _3: usize;
|
||||||
let mut _5: bool;
|
let mut _5: std::ptr::NonNull<[T]>;
|
||||||
let mut _6: usize;
|
let mut _10: bool;
|
||||||
let mut _8: usize;
|
let mut _11: *mut T;
|
||||||
let mut _9: *mut T;
|
let mut _12: *mut T;
|
||||||
let mut _11: std::ptr::NonNull<T>;
|
let mut _14: *const T;
|
||||||
let mut _12: *const T;
|
|
||||||
scope 5 {
|
scope 5 {
|
||||||
debug ptr => _4;
|
debug len => _3;
|
||||||
|
let _9: std::ptr::NonNull<T>;
|
||||||
scope 6 {
|
scope 6 {
|
||||||
let _7: *const T;
|
debug ptr => _9;
|
||||||
scope 7 {
|
scope 7 {
|
||||||
debug end_or_len => _7;
|
let _13: *const T;
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked) {
|
scope 8 {
|
||||||
debug ptr => _9;
|
debug end_or_len => _13;
|
||||||
let mut _10: *const T;
|
}
|
||||||
let mut _22: *mut T;
|
scope 14 (inlined invalid::<T>) {
|
||||||
scope 14 {
|
debug addr => _3;
|
||||||
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
|
scope 15 {
|
||||||
debug ptr => _22;
|
}
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
|
}
|
||||||
debug self => _22;
|
scope 16 (inlined NonNull::<T>::as_ptr) {
|
||||||
let mut _23: *mut u8;
|
debug self => _9;
|
||||||
scope 17 {
|
}
|
||||||
scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
|
||||||
debug ptr => _23;
|
debug self => _11;
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
debug count => _3;
|
||||||
debug self => _23;
|
scope 18 {
|
||||||
scope 20 {
|
|
||||||
scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _23;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 9 (inlined invalid::<T>) {
|
}
|
||||||
debug addr => _8;
|
scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
|
||||||
scope 10 {
|
debug reference => _1;
|
||||||
}
|
let mut _4: *const [T];
|
||||||
|
scope 10 {
|
||||||
}
|
}
|
||||||
scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
|
}
|
||||||
debug self => _4;
|
scope 11 (inlined NonNull::<[T]>::cast::<T>) {
|
||||||
debug count => _6;
|
debug self => _5;
|
||||||
scope 12 {
|
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::<impl [T]>::as_ptr) {
|
|
||||||
debug self => _1;
|
|
||||||
let mut _3: *const [T];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
|
scope 19 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
|
||||||
debug self => _13;
|
debug self => _15;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_4);
|
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = &raw const (*_1);
|
StorageLive(_9);
|
||||||
_4 = move _3 as *const T (PtrToPtr);
|
StorageLive(_4);
|
||||||
StorageDead(_3);
|
StorageLive(_8);
|
||||||
StorageLive(_7);
|
_3 = Len((*_1));
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = const _;
|
_4 = &raw const (*_1);
|
||||||
switchInt(move _5) -> [0: bb1, otherwise: bb2];
|
_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::<T> { pointer: _8 };
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_13);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = const _;
|
||||||
|
switchInt(move _10) -> [0: bb1, otherwise: bb2];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_6);
|
StorageLive(_12);
|
||||||
_6 = Len((*_1));
|
StorageLive(_11);
|
||||||
_7 = Offset(_4, _6);
|
_11 = _8 as *mut T (PtrToPtr);
|
||||||
StorageDead(_6);
|
_12 = Offset(_11, _3);
|
||||||
|
StorageDead(_11);
|
||||||
|
_13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
|
||||||
|
StorageDead(_12);
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageLive(_8);
|
_13 = _3 as *const T (Transmute);
|
||||||
_8 = Len((*_1));
|
|
||||||
_7 = _8 as *const T (Transmute);
|
|
||||||
StorageDead(_8);
|
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
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::<T> { pointer: _10 };
|
|
||||||
StorageDead(_23);
|
|
||||||
StorageDead(_22);
|
|
||||||
StorageDead(_10);
|
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);
|
StorageLive(_14);
|
||||||
_14 = _13;
|
_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;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
StorageLive(_16);
|
StorageLive(_18);
|
||||||
StorageLive(_15);
|
StorageLive(_17);
|
||||||
_15 = &mut _14;
|
_17 = &mut _16;
|
||||||
_16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind unreachable];
|
_18 = <std::slice::Iter<'_, T> as Iterator>::next(move _17) -> [return: bb5, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
StorageDead(_15);
|
StorageDead(_17);
|
||||||
_17 = discriminant(_16);
|
_19 = discriminant(_18);
|
||||||
switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
|
switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
|
StorageDead(_18);
|
||||||
StorageDead(_16);
|
StorageDead(_16);
|
||||||
StorageDead(_14);
|
|
||||||
drop(_2) -> [return: bb7, unwind unreachable];
|
drop(_2) -> [return: bb7, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8: {
|
bb8: {
|
||||||
_18 = ((_16 as Some).0: &T);
|
_20 = ((_18 as Some).0: &T);
|
||||||
StorageLive(_19);
|
StorageLive(_21);
|
||||||
_19 = &_2;
|
_21 = &_2;
|
||||||
StorageLive(_20);
|
StorageLive(_22);
|
||||||
_20 = (_18,);
|
_22 = (_20,);
|
||||||
_21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind unreachable];
|
_23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageDead(_20);
|
StorageDead(_22);
|
||||||
StorageDead(_19);
|
StorageDead(_21);
|
||||||
StorageDead(_16);
|
StorageDead(_18);
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
debug f => _2;
|
debug f => _2;
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
let mut _13: std::slice::Iter<'_, T>;
|
let mut _15: std::slice::Iter<'_, T>;
|
||||||
let mut _14: std::slice::Iter<'_, T>;
|
let mut _16: std::slice::Iter<'_, T>;
|
||||||
let mut _15: &mut std::slice::Iter<'_, T>;
|
let mut _17: &mut std::slice::Iter<'_, T>;
|
||||||
let mut _16: std::option::Option<&T>;
|
let mut _18: std::option::Option<&T>;
|
||||||
let mut _17: isize;
|
let mut _19: isize;
|
||||||
let mut _19: &impl Fn(&T);
|
let mut _21: &impl Fn(&T);
|
||||||
let mut _20: (&T,);
|
let mut _22: (&T,);
|
||||||
let _21: ();
|
let _23: ();
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug iter => _14;
|
debug iter => _16;
|
||||||
let _18: &T;
|
let _20: &T;
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug x => _18;
|
debug x => _20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
let _4: *const T;
|
let _3: usize;
|
||||||
let mut _5: bool;
|
let mut _5: std::ptr::NonNull<[T]>;
|
||||||
let mut _6: usize;
|
let mut _10: bool;
|
||||||
let mut _8: usize;
|
let mut _11: *mut T;
|
||||||
let mut _9: *mut T;
|
let mut _12: *mut T;
|
||||||
let mut _11: std::ptr::NonNull<T>;
|
let mut _14: *const T;
|
||||||
let mut _12: *const T;
|
|
||||||
scope 5 {
|
scope 5 {
|
||||||
debug ptr => _4;
|
debug len => _3;
|
||||||
|
let _9: std::ptr::NonNull<T>;
|
||||||
scope 6 {
|
scope 6 {
|
||||||
let _7: *const T;
|
debug ptr => _9;
|
||||||
scope 7 {
|
scope 7 {
|
||||||
debug end_or_len => _7;
|
let _13: *const T;
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked) {
|
scope 8 {
|
||||||
debug ptr => _9;
|
debug end_or_len => _13;
|
||||||
let mut _10: *const T;
|
}
|
||||||
let mut _22: *mut T;
|
scope 14 (inlined invalid::<T>) {
|
||||||
scope 14 {
|
debug addr => _3;
|
||||||
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
|
scope 15 {
|
||||||
debug ptr => _22;
|
}
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
|
}
|
||||||
debug self => _22;
|
scope 16 (inlined NonNull::<T>::as_ptr) {
|
||||||
let mut _23: *mut u8;
|
debug self => _9;
|
||||||
scope 17 {
|
}
|
||||||
scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
|
||||||
debug ptr => _23;
|
debug self => _11;
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
debug count => _3;
|
||||||
debug self => _23;
|
scope 18 {
|
||||||
scope 20 {
|
|
||||||
scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _23;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 9 (inlined invalid::<T>) {
|
}
|
||||||
debug addr => _8;
|
scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
|
||||||
scope 10 {
|
debug reference => _1;
|
||||||
}
|
let mut _4: *const [T];
|
||||||
|
scope 10 {
|
||||||
}
|
}
|
||||||
scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
|
}
|
||||||
debug self => _4;
|
scope 11 (inlined NonNull::<[T]>::cast::<T>) {
|
||||||
debug count => _6;
|
debug self => _5;
|
||||||
scope 12 {
|
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::<impl [T]>::as_ptr) {
|
|
||||||
debug self => _1;
|
|
||||||
let mut _3: *const [T];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
|
scope 19 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
|
||||||
debug self => _13;
|
debug self => _15;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_4);
|
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = &raw const (*_1);
|
StorageLive(_9);
|
||||||
_4 = move _3 as *const T (PtrToPtr);
|
StorageLive(_4);
|
||||||
StorageDead(_3);
|
StorageLive(_8);
|
||||||
StorageLive(_7);
|
_3 = Len((*_1));
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = const _;
|
_4 = &raw const (*_1);
|
||||||
switchInt(move _5) -> [0: bb1, otherwise: bb2];
|
_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::<T> { pointer: _8 };
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_13);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = const _;
|
||||||
|
switchInt(move _10) -> [0: bb1, otherwise: bb2];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_6);
|
StorageLive(_12);
|
||||||
_6 = Len((*_1));
|
StorageLive(_11);
|
||||||
_7 = Offset(_4, _6);
|
_11 = _8 as *mut T (PtrToPtr);
|
||||||
StorageDead(_6);
|
_12 = Offset(_11, _3);
|
||||||
|
StorageDead(_11);
|
||||||
|
_13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
|
||||||
|
StorageDead(_12);
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageLive(_8);
|
_13 = _3 as *const T (Transmute);
|
||||||
_8 = Len((*_1));
|
|
||||||
_7 = _8 as *const T (Transmute);
|
|
||||||
StorageDead(_8);
|
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
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::<T> { pointer: _10 };
|
|
||||||
StorageDead(_23);
|
|
||||||
StorageDead(_22);
|
|
||||||
StorageDead(_10);
|
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);
|
StorageLive(_14);
|
||||||
_14 = _13;
|
_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;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
StorageLive(_16);
|
StorageLive(_18);
|
||||||
StorageLive(_15);
|
StorageLive(_17);
|
||||||
_15 = &mut _14;
|
_17 = &mut _16;
|
||||||
_16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind: bb11];
|
_18 = <std::slice::Iter<'_, T> as Iterator>::next(move _17) -> [return: bb5, unwind: bb11];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
StorageDead(_15);
|
StorageDead(_17);
|
||||||
_17 = discriminant(_16);
|
_19 = discriminant(_18);
|
||||||
switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
|
switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
|
StorageDead(_18);
|
||||||
StorageDead(_16);
|
StorageDead(_16);
|
||||||
StorageDead(_14);
|
|
||||||
drop(_2) -> [return: bb7, unwind continue];
|
drop(_2) -> [return: bb7, unwind continue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8: {
|
bb8: {
|
||||||
_18 = ((_16 as Some).0: &T);
|
_20 = ((_18 as Some).0: &T);
|
||||||
StorageLive(_19);
|
StorageLive(_21);
|
||||||
_19 = &_2;
|
_21 = &_2;
|
||||||
StorageLive(_20);
|
StorageLive(_22);
|
||||||
_20 = (_18,);
|
_22 = (_20,);
|
||||||
_21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
|
_23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageDead(_20);
|
StorageDead(_22);
|
||||||
StorageDead(_19);
|
StorageDead(_21);
|
||||||
StorageDead(_16);
|
StorageDead(_18);
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
debug f => _2;
|
debug f => _2;
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
let mut _13: std::slice::Iter<'_, T>;
|
let mut _15: std::slice::Iter<'_, T>;
|
||||||
let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
|
let mut _16: std::iter::Rev<std::slice::Iter<'_, T>>;
|
||||||
let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>;
|
let mut _17: std::iter::Rev<std::slice::Iter<'_, T>>;
|
||||||
let mut _16: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
|
let mut _18: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
|
||||||
let mut _18: std::option::Option<&T>;
|
let mut _20: std::option::Option<&T>;
|
||||||
let mut _19: isize;
|
let mut _21: isize;
|
||||||
let mut _21: &impl Fn(&T);
|
let mut _23: &impl Fn(&T);
|
||||||
let mut _22: (&T,);
|
let mut _24: (&T,);
|
||||||
let _23: ();
|
let _25: ();
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug iter => _15;
|
debug iter => _17;
|
||||||
let _20: &T;
|
let _22: &T;
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug x => _20;
|
debug x => _22;
|
||||||
}
|
}
|
||||||
scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
|
scope 22 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
|
||||||
debug self => _16;
|
debug self => _18;
|
||||||
let mut _17: &mut std::slice::Iter<'_, T>;
|
let mut _19: &mut std::slice::Iter<'_, T>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
let _4: *const T;
|
let _3: usize;
|
||||||
let mut _5: bool;
|
let mut _5: std::ptr::NonNull<[T]>;
|
||||||
let mut _6: usize;
|
let mut _10: bool;
|
||||||
let mut _8: usize;
|
let mut _11: *mut T;
|
||||||
let mut _9: *mut T;
|
let mut _12: *mut T;
|
||||||
let mut _11: std::ptr::NonNull<T>;
|
let mut _14: *const T;
|
||||||
let mut _12: *const T;
|
|
||||||
scope 5 {
|
scope 5 {
|
||||||
debug ptr => _4;
|
debug len => _3;
|
||||||
|
let _9: std::ptr::NonNull<T>;
|
||||||
scope 6 {
|
scope 6 {
|
||||||
let _7: *const T;
|
debug ptr => _9;
|
||||||
scope 7 {
|
scope 7 {
|
||||||
debug end_or_len => _7;
|
let _13: *const T;
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked) {
|
scope 8 {
|
||||||
debug ptr => _9;
|
debug end_or_len => _13;
|
||||||
let mut _10: *const T;
|
}
|
||||||
let mut _24: *mut T;
|
scope 14 (inlined invalid::<T>) {
|
||||||
scope 14 {
|
debug addr => _3;
|
||||||
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
|
scope 15 {
|
||||||
debug ptr => _24;
|
}
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
|
}
|
||||||
debug self => _24;
|
scope 16 (inlined NonNull::<T>::as_ptr) {
|
||||||
let mut _25: *mut u8;
|
debug self => _9;
|
||||||
scope 17 {
|
}
|
||||||
scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
|
||||||
debug ptr => _25;
|
debug self => _11;
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
debug count => _3;
|
||||||
debug self => _25;
|
scope 18 {
|
||||||
scope 20 {
|
|
||||||
scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 9 (inlined invalid::<T>) {
|
}
|
||||||
debug addr => _8;
|
scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
|
||||||
scope 10 {
|
debug reference => _1;
|
||||||
}
|
let mut _4: *const [T];
|
||||||
|
scope 10 {
|
||||||
}
|
}
|
||||||
scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
|
}
|
||||||
debug self => _4;
|
scope 11 (inlined NonNull::<[T]>::cast::<T>) {
|
||||||
debug count => _6;
|
debug self => _5;
|
||||||
scope 12 {
|
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::<impl [T]>::as_ptr) {
|
|
||||||
debug self => _1;
|
|
||||||
let mut _3: *const [T];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
|
scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
|
||||||
debug self => _13;
|
debug self => _15;
|
||||||
scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
|
scope 20 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
|
||||||
debug iter => _13;
|
debug iter => _15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
|
scope 21 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
|
||||||
debug self => _14;
|
debug self => _16;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_13);
|
StorageLive(_15);
|
||||||
StorageLive(_4);
|
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = &raw const (*_1);
|
StorageLive(_9);
|
||||||
_4 = move _3 as *const T (PtrToPtr);
|
StorageLive(_4);
|
||||||
StorageDead(_3);
|
StorageLive(_8);
|
||||||
StorageLive(_7);
|
_3 = Len((*_1));
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = const _;
|
_4 = &raw const (*_1);
|
||||||
switchInt(move _5) -> [0: bb1, otherwise: bb2];
|
_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::<T> { pointer: _8 };
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_13);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = const _;
|
||||||
|
switchInt(move _10) -> [0: bb1, otherwise: bb2];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_6);
|
StorageLive(_12);
|
||||||
_6 = Len((*_1));
|
StorageLive(_11);
|
||||||
_7 = Offset(_4, _6);
|
_11 = _8 as *mut T (PtrToPtr);
|
||||||
StorageDead(_6);
|
_12 = Offset(_11, _3);
|
||||||
|
StorageDead(_11);
|
||||||
|
_13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
|
||||||
|
StorageDead(_12);
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageLive(_8);
|
_13 = _3 as *const T (Transmute);
|
||||||
_8 = Len((*_1));
|
|
||||||
_7 = _8 as *const T (Transmute);
|
|
||||||
StorageDead(_8);
|
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
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::<T> { pointer: _10 };
|
|
||||||
StorageDead(_25);
|
|
||||||
StorageDead(_24);
|
|
||||||
StorageDead(_10);
|
StorageDead(_10);
|
||||||
StorageDead(_9);
|
StorageLive(_14);
|
||||||
StorageLive(_12);
|
_14 = _13;
|
||||||
_12 = _7;
|
_15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
|
||||||
_13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
|
StorageDead(_14);
|
||||||
StorageDead(_12);
|
|
||||||
StorageDead(_11);
|
|
||||||
StorageDead(_7);
|
|
||||||
StorageDead(_4);
|
|
||||||
_14 = Rev::<std::slice::Iter<'_, T>> { iter: _13 };
|
|
||||||
StorageDead(_13);
|
StorageDead(_13);
|
||||||
StorageLive(_15);
|
StorageDead(_8);
|
||||||
_15 = _14;
|
StorageDead(_4);
|
||||||
|
StorageDead(_9);
|
||||||
|
StorageDead(_3);
|
||||||
|
_16 = Rev::<std::slice::Iter<'_, T>> { iter: _15 };
|
||||||
|
StorageDead(_15);
|
||||||
|
StorageLive(_17);
|
||||||
|
_17 = _16;
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
StorageLive(_18);
|
StorageLive(_20);
|
||||||
_16 = &mut _15;
|
_18 = &mut _17;
|
||||||
StorageLive(_17);
|
StorageLive(_19);
|
||||||
_17 = &mut (_15.0: std::slice::Iter<'_, T>);
|
_19 = &mut (_17.0: std::slice::Iter<'_, T>);
|
||||||
_18 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable];
|
_20 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
StorageDead(_17);
|
StorageDead(_19);
|
||||||
_19 = discriminant(_18);
|
_21 = discriminant(_20);
|
||||||
switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10];
|
switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
StorageDead(_18);
|
StorageDead(_20);
|
||||||
StorageDead(_15);
|
StorageDead(_17);
|
||||||
drop(_2) -> [return: bb7, unwind unreachable];
|
drop(_2) -> [return: bb7, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8: {
|
bb8: {
|
||||||
_20 = ((_18 as Some).0: &T);
|
_22 = ((_20 as Some).0: &T);
|
||||||
StorageLive(_21);
|
StorageLive(_23);
|
||||||
_21 = &_2;
|
_23 = &_2;
|
||||||
StorageLive(_22);
|
StorageLive(_24);
|
||||||
_22 = (_20,);
|
_24 = (_22,);
|
||||||
_23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable];
|
_25 = <impl Fn(&T) as Fn<(&T,)>>::call(move _23, move _24) -> [return: bb9, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageDead(_22);
|
StorageDead(_24);
|
||||||
StorageDead(_21);
|
StorageDead(_23);
|
||||||
StorageDead(_18);
|
StorageDead(_20);
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
debug f => _2;
|
debug f => _2;
|
||||||
let mut _0: ();
|
let mut _0: ();
|
||||||
let mut _13: std::slice::Iter<'_, T>;
|
let mut _15: std::slice::Iter<'_, T>;
|
||||||
let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
|
let mut _16: std::iter::Rev<std::slice::Iter<'_, T>>;
|
||||||
let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>;
|
let mut _17: std::iter::Rev<std::slice::Iter<'_, T>>;
|
||||||
let mut _16: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
|
let mut _18: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
|
||||||
let mut _18: std::option::Option<&T>;
|
let mut _20: std::option::Option<&T>;
|
||||||
let mut _19: isize;
|
let mut _21: isize;
|
||||||
let mut _21: &impl Fn(&T);
|
let mut _23: &impl Fn(&T);
|
||||||
let mut _22: (&T,);
|
let mut _24: (&T,);
|
||||||
let _23: ();
|
let _25: ();
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug iter => _15;
|
debug iter => _17;
|
||||||
let _20: &T;
|
let _22: &T;
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug x => _20;
|
debug x => _22;
|
||||||
}
|
}
|
||||||
scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
|
scope 22 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
|
||||||
debug self => _16;
|
debug self => _18;
|
||||||
let mut _17: &mut std::slice::Iter<'_, T>;
|
let mut _19: &mut std::slice::Iter<'_, T>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
scope 3 (inlined core::slice::<impl [T]>::iter) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
scope 4 (inlined std::slice::Iter::<'_, T>::new) {
|
||||||
debug slice => _1;
|
debug slice => _1;
|
||||||
let _4: *const T;
|
let _3: usize;
|
||||||
let mut _5: bool;
|
let mut _5: std::ptr::NonNull<[T]>;
|
||||||
let mut _6: usize;
|
let mut _10: bool;
|
||||||
let mut _8: usize;
|
let mut _11: *mut T;
|
||||||
let mut _9: *mut T;
|
let mut _12: *mut T;
|
||||||
let mut _11: std::ptr::NonNull<T>;
|
let mut _14: *const T;
|
||||||
let mut _12: *const T;
|
|
||||||
scope 5 {
|
scope 5 {
|
||||||
debug ptr => _4;
|
debug len => _3;
|
||||||
|
let _9: std::ptr::NonNull<T>;
|
||||||
scope 6 {
|
scope 6 {
|
||||||
let _7: *const T;
|
debug ptr => _9;
|
||||||
scope 7 {
|
scope 7 {
|
||||||
debug end_or_len => _7;
|
let _13: *const T;
|
||||||
scope 13 (inlined NonNull::<T>::new_unchecked) {
|
scope 8 {
|
||||||
debug ptr => _9;
|
debug end_or_len => _13;
|
||||||
let mut _10: *const T;
|
}
|
||||||
let mut _24: *mut T;
|
scope 14 (inlined invalid::<T>) {
|
||||||
scope 14 {
|
debug addr => _3;
|
||||||
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
|
scope 15 {
|
||||||
debug ptr => _24;
|
}
|
||||||
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
|
}
|
||||||
debug self => _24;
|
scope 16 (inlined NonNull::<T>::as_ptr) {
|
||||||
let mut _25: *mut u8;
|
debug self => _9;
|
||||||
scope 17 {
|
}
|
||||||
scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
|
scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
|
||||||
debug ptr => _25;
|
debug self => _11;
|
||||||
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
|
debug count => _3;
|
||||||
debug self => _25;
|
scope 18 {
|
||||||
scope 20 {
|
|
||||||
scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
|
|
||||||
debug self => _25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 9 (inlined invalid::<T>) {
|
}
|
||||||
debug addr => _8;
|
scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
|
||||||
scope 10 {
|
debug reference => _1;
|
||||||
}
|
let mut _4: *const [T];
|
||||||
|
scope 10 {
|
||||||
}
|
}
|
||||||
scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
|
}
|
||||||
debug self => _4;
|
scope 11 (inlined NonNull::<[T]>::cast::<T>) {
|
||||||
debug count => _6;
|
debug self => _5;
|
||||||
scope 12 {
|
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::<impl [T]>::as_ptr) {
|
|
||||||
debug self => _1;
|
|
||||||
let mut _3: *const [T];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
|
scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
|
||||||
debug self => _13;
|
debug self => _15;
|
||||||
scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
|
scope 20 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
|
||||||
debug iter => _13;
|
debug iter => _15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
|
scope 21 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
|
||||||
debug self => _14;
|
debug self => _16;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_13);
|
StorageLive(_15);
|
||||||
StorageLive(_4);
|
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = &raw const (*_1);
|
StorageLive(_9);
|
||||||
_4 = move _3 as *const T (PtrToPtr);
|
StorageLive(_4);
|
||||||
StorageDead(_3);
|
StorageLive(_8);
|
||||||
StorageLive(_7);
|
_3 = Len((*_1));
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = const _;
|
_4 = &raw const (*_1);
|
||||||
switchInt(move _5) -> [0: bb1, otherwise: bb2];
|
_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::<T> { pointer: _8 };
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_13);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = const _;
|
||||||
|
switchInt(move _10) -> [0: bb1, otherwise: bb2];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_6);
|
StorageLive(_12);
|
||||||
_6 = Len((*_1));
|
StorageLive(_11);
|
||||||
_7 = Offset(_4, _6);
|
_11 = _8 as *mut T (PtrToPtr);
|
||||||
StorageDead(_6);
|
_12 = Offset(_11, _3);
|
||||||
|
StorageDead(_11);
|
||||||
|
_13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
|
||||||
|
StorageDead(_12);
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageLive(_8);
|
_13 = _3 as *const T (Transmute);
|
||||||
_8 = Len((*_1));
|
|
||||||
_7 = _8 as *const T (Transmute);
|
|
||||||
StorageDead(_8);
|
|
||||||
goto -> bb3;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
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::<T> { pointer: _10 };
|
|
||||||
StorageDead(_25);
|
|
||||||
StorageDead(_24);
|
|
||||||
StorageDead(_10);
|
StorageDead(_10);
|
||||||
StorageDead(_9);
|
StorageLive(_14);
|
||||||
StorageLive(_12);
|
_14 = _13;
|
||||||
_12 = _7;
|
_15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
|
||||||
_13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
|
StorageDead(_14);
|
||||||
StorageDead(_12);
|
|
||||||
StorageDead(_11);
|
|
||||||
StorageDead(_7);
|
|
||||||
StorageDead(_4);
|
|
||||||
_14 = Rev::<std::slice::Iter<'_, T>> { iter: _13 };
|
|
||||||
StorageDead(_13);
|
StorageDead(_13);
|
||||||
StorageLive(_15);
|
StorageDead(_8);
|
||||||
_15 = _14;
|
StorageDead(_4);
|
||||||
|
StorageDead(_9);
|
||||||
|
StorageDead(_3);
|
||||||
|
_16 = Rev::<std::slice::Iter<'_, T>> { iter: _15 };
|
||||||
|
StorageDead(_15);
|
||||||
|
StorageLive(_17);
|
||||||
|
_17 = _16;
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
StorageLive(_18);
|
StorageLive(_20);
|
||||||
_16 = &mut _15;
|
_18 = &mut _17;
|
||||||
StorageLive(_17);
|
StorageLive(_19);
|
||||||
_17 = &mut (_15.0: std::slice::Iter<'_, T>);
|
_19 = &mut (_17.0: std::slice::Iter<'_, T>);
|
||||||
_18 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11];
|
_20 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind: bb11];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
StorageDead(_17);
|
StorageDead(_19);
|
||||||
_19 = discriminant(_18);
|
_21 = discriminant(_20);
|
||||||
switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10];
|
switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
StorageDead(_18);
|
StorageDead(_20);
|
||||||
StorageDead(_15);
|
StorageDead(_17);
|
||||||
drop(_2) -> [return: bb7, unwind continue];
|
drop(_2) -> [return: bb7, unwind continue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8: {
|
bb8: {
|
||||||
_20 = ((_18 as Some).0: &T);
|
_22 = ((_20 as Some).0: &T);
|
||||||
StorageLive(_21);
|
StorageLive(_23);
|
||||||
_21 = &_2;
|
_23 = &_2;
|
||||||
StorageLive(_22);
|
StorageLive(_24);
|
||||||
_22 = (_20,);
|
_24 = (_22,);
|
||||||
_23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11];
|
_25 = <impl Fn(&T) as Fn<(&T,)>>::call(move _23, move _24) -> [return: bb9, unwind: bb11];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageDead(_22);
|
StorageDead(_24);
|
||||||
StorageDead(_21);
|
StorageDead(_23);
|
||||||
StorageDead(_18);
|
StorageDead(_20);
|
||||||
goto -> bb4;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
capacity overflow
|
||||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||||
|
|
11
tests/ui/precondition-checks/misaligned-slice.rs
Normal file
11
tests/ui/precondition-checks/misaligned-slice.rs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
11
tests/ui/precondition-checks/null-slice.rs
Normal file
11
tests/ui/precondition-checks/null-slice.rs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
12
tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
Normal file
12
tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue