Remove Rvalue::Len.

This commit is contained in:
Camille Gillot 2025-09-14 22:29:04 +00:00
parent a9d0a6f155
commit 53b91ea87f
46 changed files with 656 additions and 291 deletions

View file

@ -1557,9 +1557,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
);
}
&(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
&Rvalue::Discriminant(place) => {
let af = match *rvalue {
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
Rvalue::Discriminant(..) => None,
_ => unreachable!(),
};

View file

@ -306,16 +306,11 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
self.consume_operand(location, op);
}
&(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
let af = match rvalue {
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
Rvalue::Discriminant(..) => None,
_ => unreachable!(),
};
&Rvalue::Discriminant(place) => {
self.access_place(
location,
place,
(Shallow(af), Read(ReadKind::Copy)),
(Shallow(None), Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
);
}

View file

@ -1631,7 +1631,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
| Rvalue::BinaryOp(..)
| Rvalue::RawPtr(..)
| Rvalue::ThreadLocalRef(..)
| Rvalue::Len(..)
| Rvalue::Discriminant(..)
| Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
}
@ -2201,7 +2200,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
| Rvalue::Repeat(..)
| Rvalue::Ref(..)
| Rvalue::RawPtr(..)
| Rvalue::Len(..)
| Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::BinaryOp(..)

View file

@ -834,12 +834,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
fx.bcx.ins().nop();
}
}
Rvalue::Len(place) => {
let place = codegen_place(fx, place);
let usize_layout = fx.layout_of(fx.tcx.types.usize);
let len = codegen_array_len(fx, place);
lval.write_cvalue(fx, CValue::by_val(len, usize_layout));
}
Rvalue::ShallowInitBox(ref operand, content_ty) => {
let content_ty = fx.monomorphize(content_ty);
let box_layout = fx.layout_of(Ty::new_box(fx.tcx, content_ty));

View file

@ -7,9 +7,9 @@ use rustc_middle::{bug, mir, span_bug};
use rustc_session::config::OptLevel;
use tracing::{debug, instrument};
use super::FunctionCx;
use super::operand::{OperandRef, OperandRefBuilder, OperandValue};
use super::place::{PlaceRef, PlaceValue, codegen_tag_value};
use super::{FunctionCx, LocalRef};
use crate::common::{IntPredicate, TypeKind};
use crate::traits::*;
use crate::{MemFlags, base};
@ -510,14 +510,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.codegen_place_to_pointer(bx, place, mk_ptr)
}
mir::Rvalue::Len(place) => {
let size = self.evaluate_array_len(bx, place);
OperandRef {
val: OperandValue::Immediate(size),
layout: bx.cx().layout_of(bx.tcx().types.usize),
}
}
mir::Rvalue::BinaryOp(op_with_overflow, box (ref lhs, ref rhs))
if let Some(op) = op_with_overflow.overflowing_to_wrapping() =>
{
@ -749,21 +741,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
fn evaluate_array_len(&mut self, bx: &mut Bx, place: mir::Place<'tcx>) -> Bx::Value {
// ZST are passed as operands and require special handling
// because codegen_place() panics if Local is operand.
if let Some(index) = place.as_local()
&& let LocalRef::Operand(op) = self.locals[index]
&& let ty::Array(_, n) = op.layout.ty.kind()
{
let n = n.try_to_target_usize(bx.tcx()).expect("expected monomorphic const in codegen");
return bx.cx().const_usize(n);
}
// use common size calculation for non zero-sized types
let cg_value = self.codegen_place(bx, place.as_ref());
cg_value.len(bx.cx())
}
/// Codegen an `Rvalue::RawPtr` or `Rvalue::Ref`
fn codegen_place_to_pointer(
&mut self,

View file

@ -573,8 +573,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
Rvalue::Use(_)
| Rvalue::CopyForDeref(..)
| Rvalue::Repeat(..)
| Rvalue::Discriminant(..)
| Rvalue::Len(_) => {}
| Rvalue::Discriminant(..) => {}
Rvalue::Aggregate(kind, ..) => {
if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref()

View file

@ -232,9 +232,7 @@ where
Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx))
}
Rvalue::Discriminant(place) | Rvalue::Len(place) => {
in_place::<Q, _>(cx, in_local, place.as_ref())
}
Rvalue::Discriminant(place) => in_place::<Q, _>(cx, in_local, place.as_ref()),
Rvalue::CopyForDeref(place) => in_place::<Q, _>(cx, in_local, place.as_ref()),

View file

@ -197,7 +197,6 @@ where
| mir::Rvalue::CopyForDeref(..)
| mir::Rvalue::ThreadLocalRef(..)
| mir::Rvalue::Repeat(..)
| mir::Rvalue::Len(..)
| mir::Rvalue::BinaryOp(..)
| mir::Rvalue::NullaryOp(..)
| mir::Rvalue::UnaryOp(..)

View file

@ -17,7 +17,7 @@ use tracing::{info, instrument, trace};
use super::{
FnArg, FnVal, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemPlaceMeta, PlaceTy,
Projectable, Scalar, interp_ok, throw_ub, throw_unsup_format,
Projectable, interp_ok, throw_ub, throw_unsup_format,
};
use crate::interpret::EnteredTraceSpan;
use crate::{enter_trace_span, util};
@ -225,12 +225,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.write_repeat(operand, &dest)?;
}
Len(place) => {
let src = self.eval_place(place)?;
let len = src.len(self)?;
self.write_scalar(Scalar::from_target_usize(len, self), &dest)?;
}
Ref(_, borrow_kind, place) => {
let src = self.eval_place(place)?;
let place = self.force_allocation(&src)?;

View file

@ -1062,7 +1062,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
pretty_print_const(b, fmt, false)?;
write!(fmt, "]")
}
Len(ref a) => write!(fmt, "Len({a:?})"),
Cast(ref kind, ref place, ref ty) => {
with_no_trimmed_paths!(write!(fmt, "{place:?} as {ty} ({kind:?})"))
}

View file

@ -697,7 +697,6 @@ impl<'tcx> Rvalue<'tcx> {
| Rvalue::Ref(_, _, _)
| Rvalue::ThreadLocalRef(_)
| Rvalue::RawPtr(_, _)
| Rvalue::Len(_)
| Rvalue::Cast(
CastKind::IntToInt
| CastKind::FloatToInt
@ -739,7 +738,6 @@ impl<'tcx> Rvalue<'tcx> {
let place_ty = place.ty(local_decls, tcx).ty;
Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
}
Rvalue::Len(..) => tcx.types.usize,
Rvalue::Cast(.., ty) => ty,
Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
let lhs_ty = lhs.ty(local_decls, tcx);

View file

@ -1407,16 +1407,6 @@ pub enum Rvalue<'tcx> {
/// model.
RawPtr(RawPtrKind, Place<'tcx>),
/// Yields the length of the place, as a `usize`.
///
/// If the type of the place is an array, this is the array length. For slices (`[T]`, not
/// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is
/// ill-formed for places of other types.
///
/// This cannot be a `UnOp(PtrMetadata, _)` because that expects a value, and we only
/// have a place, and `UnOp(PtrMetadata, RawPtr(place))` is not a thing.
Len(Place<'tcx>),
/// Performs essentially all of the casts that can be performed via `as`.
///
/// This allows for casts from/to a variety of types.

View file

@ -717,14 +717,6 @@ macro_rules! make_mir_visitor {
self.visit_place(path, ctx, location);
}
Rvalue::Len(path) => {
self.visit_place(
path,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
location
);
}
Rvalue::Cast(_cast_kind, operand, ty) => {
self.visit_operand(operand, location);
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));

View file

@ -229,6 +229,11 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
let source = self.parse_operand(args[0])?;
Ok(Rvalue::Cast(CastKind::PtrToPtr, source, expr.ty))
},
@call(mir_cast_unsize, args) => {
let source = self.parse_operand(args[0])?;
let kind = CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, CoercionSource::AsCast);
Ok(Rvalue::Cast(kind, source, expr.ty))
},
@call(mir_checked, args) => {
parse_by_kind!(self, args[0], _, "binary op",
ExprKind::Binary { op, lhs, rhs } => {
@ -247,7 +252,6 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
let offset = self.parse_operand(args[1])?;
Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
},
@call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
@call(mir_ptr_metadata, args) => Ok(Rvalue::UnaryOp(UnOp::PtrMetadata, self.parse_operand(args[0])?)),
@call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
ExprKind::Borrow { borrow_kind, arg } => Ok(

View file

@ -663,7 +663,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// For arrays it'll be `Operand::Constant` with the actual length;
/// For slices it'll be `Operand::Move` of a local using `PtrMetadata`.
fn len_of_slice_or_array(
pub(in crate::builder) fn len_of_slice_or_array(
&mut self,
block: BasicBlock,
place: Place<'tcx>,

View file

@ -309,7 +309,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let actual = self.temp(usize_ty, test.span);
// actual = len(place)
self.cfg.push_assign(block, source_info, actual, Rvalue::Len(place));
let length_op = self.len_of_slice_or_array(block, place, test.span, source_info);
self.cfg.push_assign(block, source_info, actual, Rvalue::Use(length_op));
// expected = <N>
let expected = self.push_usize(block, source_info, len);

View file

@ -91,7 +91,6 @@ where
| Rvalue::Use(..)
| Rvalue::ThreadLocalRef(..)
| Rvalue::Repeat(..)
| Rvalue::Len(..)
| Rvalue::BinaryOp(..)
| Rvalue::NullaryOp(..)
| Rvalue::UnaryOp(..)

View file

@ -413,7 +413,6 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
Rvalue::Ref(..)
| Rvalue::RawPtr(..)
| Rvalue::Discriminant(..)
| Rvalue::Len(..)
| Rvalue::NullaryOp(
NullOp::SizeOf
| NullOp::AlignOf

View file

@ -412,18 +412,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
state: &mut State<FlatSet<Scalar>>,
) -> ValueOrPlace<FlatSet<Scalar>> {
let val = match rvalue {
Rvalue::Len(place) => {
let place_ty = place.ty(self.local_decls, self.tcx);
if let ty::Array(_, len) = place_ty.ty.kind() {
Const::Ty(self.tcx.types.usize, *len)
.try_eval_scalar(self.tcx, self.typing_env)
.map_or(FlatSet::Top, FlatSet::Elem)
} else if let [ProjectionElem::Deref] = place.projection[..] {
state.get_len(place.local.into(), &self.map)
} else {
FlatSet::Top
}
}
Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => {
let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
@ -465,15 +453,23 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
let (val, _overflow) = self.binary_op(state, *op, left, right);
val
}
Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) {
FlatSet::Elem(value) => self
.ecx
.unary_op(*op, &value)
.discard_err()
.map_or(FlatSet::Top, |val| self.wrap_immediate(*val)),
FlatSet::Bottom => FlatSet::Bottom,
FlatSet::Top => FlatSet::Top,
},
Rvalue::UnaryOp(op, operand) => {
if let UnOp::PtrMetadata = op
&& let Some(place) = operand.place()
&& let Some(len) = self.map.find_len(place.as_ref())
{
return ValueOrPlace::Place(len);
}
match self.eval_operand(operand, state) {
FlatSet::Elem(value) => self
.ecx
.unary_op(*op, &value)
.discard_err()
.map_or(FlatSet::Top, |val| self.wrap_immediate(*val)),
FlatSet::Bottom => FlatSet::Bottom,
FlatSet::Top => FlatSet::Top,
}
}
Rvalue::NullaryOp(null_op, ty) => {
let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);

View file

@ -200,8 +200,6 @@ enum Value<'tcx> {
Projection(VnIndex, ProjectionElem<VnIndex, ()>),
/// Discriminant of the given value.
Discriminant(VnIndex),
/// Length of an array or slice.
Len(VnIndex),
// Operations.
NullaryOp(NullOp<'tcx>, Ty<'tcx>),
@ -477,11 +475,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
self.ecx.discriminant_for_variant(base.layout.ty, variant).discard_err()?;
discr_value.into()
}
Len(slice) => {
let slice = self.evaluated[slice].as_ref()?;
let len = slice.len(&self.ecx).discard_err()?;
ImmTy::from_uint(len, ty).into()
}
NullaryOp(null_op, arg_ty) => {
let arg_layout = self.ecx.layout_of(arg_ty).ok()?;
if let NullOp::SizeOf | NullOp::AlignOf = null_op
@ -841,7 +834,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
}
// Operations.
Rvalue::Len(ref mut place) => return self.simplify_len(place, location),
Rvalue::Cast(ref mut kind, ref mut value, to) => {
return self.simplify_cast(kind, value, to, location);
}
@ -1049,7 +1041,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
if op == UnOp::PtrMetadata {
let mut was_updated = false;
loop {
match self.get(arg_index) {
arg_index = match self.get(arg_index) {
// Pointer casts that preserve metadata, such as
// `*const [i32]` <-> `*mut [i32]` <-> `*mut [f32]`.
// It's critical that this not eliminate cases like
@ -1061,9 +1053,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
Value::Cast { kind: CastKind::PtrToPtr, value: inner }
if self.pointers_have_same_metadata(self.ty(*inner), arg_ty) =>
{
arg_index = *inner;
was_updated = true;
continue;
*inner
}
// We have an unsizing cast, which assigns the length to wide pointer metadata.
Value::Cast {
kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _),
value: from,
} if let Some(from) = self.ty(*from).builtin_deref(true)
&& let ty::Array(_, len) = from.kind()
&& let Some(to) = self.ty(arg_index).builtin_deref(true)
&& let ty::Slice(..) = to.kind() =>
{
return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
}
// `&mut *p`, `&raw *p`, etc don't change metadata.
@ -1072,18 +1074,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
place.as_ref()
&& let Some(local_index) = self.locals[local] =>
{
arg_index = local_index;
was_updated = true;
continue;
local_index
}
_ => {
if was_updated && let Some(op) = self.try_as_operand(arg_index, location) {
*arg_op = op;
}
break;
}
}
_ => break,
};
was_updated = true;
}
if was_updated && let Some(op) = self.try_as_operand(arg_index, location) {
*arg_op = op;
}
}
@ -1407,39 +1407,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
Some(self.insert(to, Value::Cast { kind, value }))
}
fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option<VnIndex> {
// Trivial case: we are fetching a statically known length.
let place_ty = place.ty(self.local_decls, self.tcx).ty;
if let ty::Array(_, len) = place_ty.kind() {
return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
}
let mut inner = self.simplify_place_value(place, location)?;
// The length information is stored in the wide pointer.
// Reborrowing copies length information from one pointer to the other.
while let Value::Address { place: borrowed, .. } = self.get(inner)
&& let [PlaceElem::Deref] = borrowed.projection[..]
&& let Some(borrowed) = self.locals[borrowed.local]
{
inner = borrowed;
}
// We have an unsizing cast, which assigns the length to wide pointer metadata.
if let Value::Cast { kind, value: from } = self.get(inner)
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
&& let Some(from) = self.ty(*from).builtin_deref(true)
&& let ty::Array(_, len) = from.kind()
&& let Some(to) = self.ty(inner).builtin_deref(true)
&& let ty::Slice(..) = to.kind()
{
return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
}
// Fallback: a symbolic `Len`.
Some(self.insert(self.tcx.types.usize, Value::Len(inner)))
}
fn pointers_have_same_metadata(&self, left_ptr_ty: Ty<'tcx>, right_ptr_ty: Ty<'tcx>) -> bool {
let left_meta_ty = left_ptr_ty.pointee_metadata_ty_or_projection(self.tcx);
let right_meta_ty = right_ptr_ty.pointee_metadata_ty_or_projection(self.tcx);

View file

@ -441,7 +441,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
| Rvalue::Use(..)
| Rvalue::CopyForDeref(..)
| Rvalue::Repeat(..)
| Rvalue::Len(..)
| Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::Discriminant(..)
@ -604,20 +603,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
return None;
}
Len(place) => {
let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind()
{
n.try_to_target_usize(self.tcx)?
} else {
match self.get_const(place)? {
Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
Value::Aggregate { fields, .. } => fields.len() as u64,
Value::Uninit => return None,
}
};
ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into()
}
Ref(..) | RawPtr(..) => return None,
NullaryOp(ref null_op, ty) => {

View file

@ -437,9 +437,7 @@ impl<'tcx> Validator<'_, 'tcx> {
self.validate_operand(op)?
}
Rvalue::Discriminant(place) | Rvalue::Len(place) => {
self.validate_place(place.as_ref())?
}
Rvalue::Discriminant(place) => self.validate_place(place.as_ref())?,
Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),

View file

@ -1064,14 +1064,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
Rvalue::Ref(..) => {}
Rvalue::Len(p) => {
let pty = p.ty(&self.body.local_decls, self.tcx).ty;
check_kinds!(
pty,
"Cannot compute length of non-array type {:?}",
ty::Array(..) | ty::Slice(..)
);
}
Rvalue::BinaryOp(op, vals) => {
use BinOp::*;
let a = vals.0.ty(&self.body.local_decls, self.tcx);

View file

@ -215,7 +215,6 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
mutability.stable(tables, cx),
place.stable(tables, cx),
),
Len(place) => crate::mir::Rvalue::Len(place.stable(tables, cx)),
Cast(cast_kind, op, ty) => crate::mir::Rvalue::Cast(
cast_kind.stable(tables, cx),
op.stable(tables, cx),

View file

@ -1413,6 +1413,7 @@ symbols! {
mir_call,
mir_cast_ptr_to_ptr,
mir_cast_transmute,
mir_cast_unsize,
mir_checked,
mir_copy_for_deref,
mir_debuginfo,

View file

@ -401,7 +401,6 @@ define!("mir_storage_dead", fn StorageDead<T>(local: T));
define!("mir_assume", fn Assume(operand: bool));
define!("mir_deinit", fn Deinit<T>(place: T));
define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
define!("mir_len", fn Len<T>(place: T) -> usize);
define!(
"mir_ptr_metadata",
fn PtrMetadata<P: ?Sized>(place: *const P) -> <P as ::core::ptr::Pointee>::Metadata
@ -491,6 +490,13 @@ define!(
/// This allows bypassing normal validation to generate strange casts.
fn CastPtrToPtr<T, U>(operand: T) -> U
);
define!(
"mir_cast_unsize",
/// Emits a `CastKind::PointerCoercion(Unsize)` cast.
///
/// This allows bypassing normal validation to generate strange casts.
fn CastUnsize<T, U>(operand: T) -> U
);
define!(
"mir_make_place",
#[doc(hidden)]

View file

@ -126,7 +126,7 @@ fn check_rvalue<'tcx>(
) -> McfResult {
match rvalue {
Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())),
Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
check_place(cx, *place, span, body, msrv)
},
Rvalue::CopyForDeref(place) => check_place(cx, *place, span, body, msrv),

View file

@ -3,12 +3,16 @@
fn arrays() -> usize {
let mut _0: usize;
let mut _1: [i32; C];
let mut _2: usize;
let mut _2: *const [i32; C];
let mut _3: *const [i32];
let mut _4: usize;
bb0: {
_1 = [const 5_i32; C];
_2 = Len(_1);
_0 = copy _2;
_2 = &raw const _1;
_3 = copy _2 as *const [i32] (PointerCoercion(Unsize, AsCast));
_4 = PtrMetadata(copy _3);
_0 = copy _4;
return;
}
}

View file

@ -10,7 +10,9 @@ fn arrays<const C: usize>() -> usize {
mir! {
{
let x = [5_i32; C];
let c = Len(x);
let y = &raw const x;
let z = CastUnsize::<_, *const [i32]>(y);
let c = PtrMetadata(z);
RET = c;
Return()
}

View file

@ -0,0 +1,77 @@
- // MIR for `main` before DataflowConstProp
+ // MIR for `main` after DataflowConstProp
fn main() -> () {
let mut _0: ();
let _1: u32;
let mut _2: &[u32];
let mut _3: &[u32; 3];
let _4: &[u32; 3];
let _5: [u32; 3];
let _6: usize;
let mut _7: usize;
let mut _8: bool;
let mut _10: &[u32];
let _11: usize;
let mut _12: usize;
let mut _13: bool;
let mut _14: &[u32; 3];
scope 1 {
debug local => _1;
let _9: u32;
scope 2 {
debug constant => _9;
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_14 = const main::promoted[0];
_4 = copy _14;
_3 = copy _4;
_2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
StorageDead(_3);
StorageLive(_6);
_6 = const 1_usize;
- _7 = PtrMetadata(copy _2);
- _8 = Lt(copy _6, copy _7);
- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
+ _7 = const 3_usize;
+ _8 = const true;
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable];
}
bb1: {
- _1 = copy (*_2)[_6];
+ _1 = copy (*_2)[1 of 2];
StorageDead(_6);
StorageDead(_4);
StorageDead(_2);
StorageLive(_9);
StorageLive(_10);
_10 = const main::SLICE;
StorageLive(_11);
_11 = const 1_usize;
- _12 = PtrMetadata(copy _10);
- _13 = Lt(copy _11, copy _12);
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable];
+ _12 = const 3_usize;
+ _13 = const true;
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable];
}
bb2: {
- _9 = copy (*_10)[_11];
+ _9 = copy (*_10)[1 of 2];
StorageDead(_11);
StorageDead(_10);
_0 = const ();
StorageDead(_9);
StorageDead(_1);
return;
}
}

View file

@ -0,0 +1,77 @@
- // MIR for `main` before DataflowConstProp
+ // MIR for `main` after DataflowConstProp
fn main() -> () {
let mut _0: ();
let _1: u32;
let mut _2: &[u32];
let mut _3: &[u32; 3];
let _4: &[u32; 3];
let _5: [u32; 3];
let _6: usize;
let mut _7: usize;
let mut _8: bool;
let mut _10: &[u32];
let _11: usize;
let mut _12: usize;
let mut _13: bool;
let mut _14: &[u32; 3];
scope 1 {
debug local => _1;
let _9: u32;
scope 2 {
debug constant => _9;
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_14 = const main::promoted[0];
_4 = copy _14;
_3 = copy _4;
_2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
StorageDead(_3);
StorageLive(_6);
_6 = const 1_usize;
- _7 = PtrMetadata(copy _2);
- _8 = Lt(copy _6, copy _7);
- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
+ _7 = const 3_usize;
+ _8 = const true;
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue];
}
bb1: {
- _1 = copy (*_2)[_6];
+ _1 = copy (*_2)[1 of 2];
StorageDead(_6);
StorageDead(_4);
StorageDead(_2);
StorageLive(_9);
StorageLive(_10);
_10 = const main::SLICE;
StorageLive(_11);
_11 = const 1_usize;
- _12 = PtrMetadata(copy _10);
- _13 = Lt(copy _11, copy _12);
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue];
+ _12 = const 3_usize;
+ _13 = const true;
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue];
}
bb2: {
- _9 = copy (*_10)[_11];
+ _9 = copy (*_10)[1 of 2];
StorageDead(_11);
StorageDead(_10);
_0 = const ();
StorageDead(_9);
StorageDead(_1);
return;
}
}

View file

@ -0,0 +1,77 @@
- // MIR for `main` before DataflowConstProp
+ // MIR for `main` after DataflowConstProp
fn main() -> () {
let mut _0: ();
let _1: u32;
let mut _2: &[u32];
let mut _3: &[u32; 3];
let _4: &[u32; 3];
let _5: [u32; 3];
let _6: usize;
let mut _7: usize;
let mut _8: bool;
let mut _10: &[u32];
let _11: usize;
let mut _12: usize;
let mut _13: bool;
let mut _14: &[u32; 3];
scope 1 {
debug local => _1;
let _9: u32;
scope 2 {
debug constant => _9;
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_14 = const main::promoted[0];
_4 = copy _14;
_3 = copy _4;
_2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
StorageDead(_3);
StorageLive(_6);
_6 = const 1_usize;
- _7 = PtrMetadata(copy _2);
- _8 = Lt(copy _6, copy _7);
- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
+ _7 = const 3_usize;
+ _8 = const true;
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable];
}
bb1: {
- _1 = copy (*_2)[_6];
+ _1 = copy (*_2)[1 of 2];
StorageDead(_6);
StorageDead(_4);
StorageDead(_2);
StorageLive(_9);
StorageLive(_10);
_10 = const main::SLICE;
StorageLive(_11);
_11 = const 1_usize;
- _12 = PtrMetadata(copy _10);
- _13 = Lt(copy _11, copy _12);
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable];
+ _12 = const 3_usize;
+ _13 = const true;
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable];
}
bb2: {
- _9 = copy (*_10)[_11];
+ _9 = copy (*_10)[1 of 2];
StorageDead(_11);
StorageDead(_10);
_0 = const ();
StorageDead(_9);
StorageDead(_1);
return;
}
}

View file

@ -0,0 +1,77 @@
- // MIR for `main` before DataflowConstProp
+ // MIR for `main` after DataflowConstProp
fn main() -> () {
let mut _0: ();
let _1: u32;
let mut _2: &[u32];
let mut _3: &[u32; 3];
let _4: &[u32; 3];
let _5: [u32; 3];
let _6: usize;
let mut _7: usize;
let mut _8: bool;
let mut _10: &[u32];
let _11: usize;
let mut _12: usize;
let mut _13: bool;
let mut _14: &[u32; 3];
scope 1 {
debug local => _1;
let _9: u32;
scope 2 {
debug constant => _9;
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_14 = const main::promoted[0];
_4 = copy _14;
_3 = copy _4;
_2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
StorageDead(_3);
StorageLive(_6);
_6 = const 1_usize;
- _7 = PtrMetadata(copy _2);
- _8 = Lt(copy _6, copy _7);
- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
+ _7 = const 3_usize;
+ _8 = const true;
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue];
}
bb1: {
- _1 = copy (*_2)[_6];
+ _1 = copy (*_2)[1 of 2];
StorageDead(_6);
StorageDead(_4);
StorageDead(_2);
StorageLive(_9);
StorageLive(_10);
_10 = const main::SLICE;
StorageLive(_11);
_11 = const 1_usize;
- _12 = PtrMetadata(copy _10);
- _13 = Lt(copy _11, copy _12);
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue];
+ _12 = const 3_usize;
+ _13 = const true;
+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue];
}
bb2: {
- _9 = copy (*_10)[_11];
+ _9 = copy (*_10)[1 of 2];
StorageDead(_11);
StorageDead(_10);
_0 = const ();
StorageDead(_9);
StorageDead(_1);
return;
}
}

View file

@ -0,0 +1,34 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ test-mir-pass: DataflowConstProp
//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR slice_len.main.DataflowConstProp.diff
// CHECK-LABEL: fn main(
fn main() {
// CHECK: debug local => [[local:_.*]];
// CHECK: debug constant => [[constant:_.*]];
// CHECK-NOT: {{_.*}} = Len(
// CHECK-NOT: {{_.*}} = Lt(
// CHECK-NOT: assert(move _
// CHECK: {{_.*}} = const 3_usize;
// CHECK: {{_.*}} = const true;
// CHECK: assert(const true,
// CHECK: [[local]] = copy (*{{_.*}})[1 of 2];
let local = (&[1u32, 2, 3] as &[u32])[1];
// CHECK-NOT: {{_.*}} = Len(
// CHECK-NOT: {{_.*}} = Lt(
// CHECK-NOT: assert(move _
const SLICE: &[u32] = &[1, 2, 3];
// CHECK: {{_.*}} = const 3_usize;
// CHECK: {{_.*}} = const true;
// CHECK: assert(const true,
// CHECK-NOT: [[constant]] = {{copy|move}} (*{{_.*}})[_
// CHECK: [[constant]] = copy (*{{_.*}})[1 of 2];
let constant = SLICE[1];
}

View file

@ -12,8 +12,7 @@
}
bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_2);
StorageLive(_3);
_3 = &(*_1);
_2 = move _3 as &[i32] (PointerCoercion(Unsize, Implicit));
@ -23,8 +22,7 @@
- _0 = PtrMetadata(move _4);
+ _0 = const 42_usize;
StorageDead(_4);
- StorageDead(_2);
+ nop;
StorageDead(_2);
return;
}
}

View file

@ -12,8 +12,7 @@
}
bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_2);
StorageLive(_3);
_3 = &(*_1);
_2 = move _3 as &[i32] (PointerCoercion(Unsize, Implicit));
@ -23,8 +22,7 @@
- _0 = PtrMetadata(move _4);
+ _0 = const 42_usize;
StorageDead(_4);
- StorageDead(_2);
+ nop;
StorageDead(_2);
return;
}
}

View file

@ -0,0 +1,71 @@
- // MIR for `norm2` before InstSimplify-after-simplifycfg
+ // MIR for `norm2` after InstSimplify-after-simplifycfg
fn norm2(_1: [f32; 2]) -> f32 {
debug x => _1;
let mut _0: f32;
let _2: f32;
let _3: usize;
let mut _4: bool;
let _6: usize;
let mut _7: bool;
let mut _8: f32;
let mut _9: f32;
let mut _10: f32;
let mut _11: f32;
let mut _12: f32;
let mut _13: f32;
scope 1 {
debug a => _2;
let _5: f32;
scope 2 {
debug b => _5;
}
}
bb0: {
StorageLive(_2);
StorageLive(_3);
_3 = const 0_usize;
_4 = Lt(copy _3, const 2_usize);
assert(move _4, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _3) -> [success: bb1, unwind unreachable];
}
bb1: {
_2 = copy _1[_3];
StorageDead(_3);
StorageLive(_5);
StorageLive(_6);
_6 = const 1_usize;
_7 = Lt(copy _6, const 2_usize);
assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb2, unwind unreachable];
}
bb2: {
_5 = copy _1[_6];
StorageDead(_6);
StorageLive(_8);
StorageLive(_9);
_9 = copy _2;
StorageLive(_10);
_10 = copy _2;
_8 = Mul(move _9, move _10);
StorageDead(_10);
StorageDead(_9);
StorageLive(_11);
StorageLive(_12);
_12 = copy _5;
StorageLive(_13);
_13 = copy _5;
_11 = Mul(move _12, move _13);
StorageDead(_13);
StorageDead(_12);
_0 = Add(move _8, move _11);
StorageDead(_11);
StorageDead(_8);
StorageDead(_5);
StorageDead(_2);
return;
}
}

View file

@ -0,0 +1,71 @@
- // MIR for `norm2` before InstSimplify-after-simplifycfg
+ // MIR for `norm2` after InstSimplify-after-simplifycfg
fn norm2(_1: [f32; 2]) -> f32 {
debug x => _1;
let mut _0: f32;
let _2: f32;
let _3: usize;
let mut _4: bool;
let _6: usize;
let mut _7: bool;
let mut _8: f32;
let mut _9: f32;
let mut _10: f32;
let mut _11: f32;
let mut _12: f32;
let mut _13: f32;
scope 1 {
debug a => _2;
let _5: f32;
scope 2 {
debug b => _5;
}
}
bb0: {
StorageLive(_2);
StorageLive(_3);
_3 = const 0_usize;
_4 = Lt(copy _3, const 2_usize);
assert(move _4, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _3) -> [success: bb1, unwind continue];
}
bb1: {
_2 = copy _1[_3];
StorageDead(_3);
StorageLive(_5);
StorageLive(_6);
_6 = const 1_usize;
_7 = Lt(copy _6, const 2_usize);
assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb2, unwind continue];
}
bb2: {
_5 = copy _1[_6];
StorageDead(_6);
StorageLive(_8);
StorageLive(_9);
_9 = copy _2;
StorageLive(_10);
_10 = copy _2;
_8 = Mul(move _9, move _10);
StorageDead(_10);
StorageDead(_9);
StorageLive(_11);
StorageLive(_12);
_12 = copy _5;
StorageLive(_13);
_13 = copy _5;
_11 = Mul(move _12, move _13);
StorageDead(_13);
StorageDead(_12);
_0 = Add(move _8, move _11);
StorageDead(_11);
StorageDead(_8);
StorageDead(_5);
StorageDead(_2);
return;
}
}

View file

@ -0,0 +1,15 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ test-mir-pass: InstSimplify-after-simplifycfg
// EMIT_MIR combine_array_len.norm2.InstSimplify-after-simplifycfg.diff
fn norm2(x: [f32; 2]) -> f32 {
// CHECK-LABEL: fn norm2(
// CHECK-NOT: Len(
let a = x[0];
let b = x[1];
a * a + b * b
}
fn main() {
assert_eq!(norm2([3.0, 4.0]), 5.0 * 5.0);
}

View file

@ -7,18 +7,16 @@
let _2: &[T];
let _3: &[T; 3];
let _4: [T; 3];
let mut _5: usize;
let mut _6: bool;
let mut _10: !;
let mut _8: !;
scope 1 {
debug v => _2;
let _5: &T;
let _6: &T;
let _7: &T;
let _8: &T;
let _9: &T;
scope 2 {
debug v1 => _7;
debug v2 => _8;
debug v3 => _9;
debug v1 => _5;
debug v2 => _6;
debug v3 => _7;
}
}
@ -27,25 +25,23 @@
_4 = [copy _1, copy _1, copy _1];
_3 = &_4;
_2 = copy _3 as &[T] (PointerCoercion(Unsize, Implicit));
nop;
nop;
goto -> bb2;
}
bb1: {
_10 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable;
_8 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable;
}
bb2: {
StorageLive(_5);
_5 = &(*_2)[0 of 3];
StorageLive(_6);
_6 = &(*_2)[1 of 3];
StorageLive(_7);
_7 = &(*_2)[0 of 3];
StorageLive(_8);
_8 = &(*_2)[1 of 3];
StorageLive(_9);
_9 = &(*_2)[2 of 3];
StorageDead(_9);
StorageDead(_8);
_7 = &(*_2)[2 of 3];
StorageDead(_7);
StorageDead(_6);
StorageDead(_5);
StorageDead(_4);
return;
}

View file

@ -7,18 +7,16 @@
let _2: &[T];
let _3: &[T; 3];
let _4: [T; 3];
let mut _5: usize;
let mut _6: bool;
let mut _10: !;
let mut _8: !;
scope 1 {
debug v => _2;
let _5: &T;
let _6: &T;
let _7: &T;
let _8: &T;
let _9: &T;
scope 2 {
debug v1 => _7;
debug v2 => _8;
debug v3 => _9;
debug v1 => _5;
debug v2 => _6;
debug v3 => _7;
}
}
@ -27,25 +25,23 @@
_4 = [copy _1, copy _1, copy _1];
_3 = &_4;
_2 = copy _3 as &[T] (PointerCoercion(Unsize, Implicit));
nop;
nop;
goto -> bb2;
}
bb1: {
_10 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue;
_8 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue;
}
bb2: {
StorageLive(_5);
_5 = &(*_2)[0 of 3];
StorageLive(_6);
_6 = &(*_2)[1 of 3];
StorageLive(_7);
_7 = &(*_2)[0 of 3];
StorageLive(_8);
_8 = &(*_2)[1 of 3];
StorageLive(_9);
_9 = &(*_2)[2 of 3];
StorageDead(_9);
StorageDead(_8);
_7 = &(*_2)[2 of 3];
StorageDead(_7);
StorageDead(_6);
StorageDead(_5);
StorageDead(_4);
return;
}

View file

@ -18,8 +18,7 @@
}
bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_4 = &_1;
@ -41,8 +40,7 @@
bb1: {
StorageDead(_6);
StorageDead(_5);
- StorageDead(_2);
+ nop;
StorageDead(_2);
StorageDead(_7);
return;
}

View file

@ -18,8 +18,7 @@
}
bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_4 = &_1;
@ -41,8 +40,7 @@
bb1: {
StorageDead(_6);
StorageDead(_5);
- StorageDead(_2);
+ nop;
StorageDead(_2);
StorageDead(_7);
return;
}

View file

@ -17,8 +17,7 @@
}
bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_4 = &mut _1;
@ -38,8 +37,7 @@
bb1: {
StorageDead(_6);
StorageDead(_5);
- StorageDead(_2);
+ nop;
StorageDead(_2);
return;
}
}

View file

@ -17,8 +17,7 @@
}
bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
_4 = &mut _1;
@ -38,8 +37,7 @@
bb1: {
StorageDead(_6);
StorageDead(_5);
- StorageDead(_2);
+ nop;
StorageDead(_2);
return;
}
}

View file

@ -17,14 +17,15 @@
let mut _15: std::ops::RangeFull;
let mut _16: usize;
let mut _17: usize;
let mut _18: bool;
let _23: &&mut u8;
let _24: &mut u8;
let mut _25: debuginfo::T;
let mut _18: usize;
let mut _19: bool;
let _24: &&mut u8;
let _25: &mut u8;
let mut _26: debuginfo::T;
scope 1 {
debug ref_mut_u8 => _1;
let _3: &u8;
let mut _28: &debuginfo::T;
let mut _29: &debuginfo::T;
scope 2 {
debug field => _3;
let _5: &u8;
@ -32,22 +33,22 @@
- debug reborrow => _5;
+ debug reborrow => _1;
let _9: &i32;
let _22: &&&mut u8;
let mut _27: &std::option::Option<i32>;
let _23: &&&mut u8;
let mut _28: &std::option::Option<i32>;
scope 4 {
debug variant_field => _9;
}
scope 5 {
debug constant_index => _19;
debug subslice => _20;
debug constant_index_from_end => _21;
let _19: &i32;
let _20: &[i32];
let _21: &i32;
let mut _26: &[i32; 10];
debug constant_index => _20;
debug subslice => _21;
debug constant_index_from_end => _22;
let _20: &i32;
let _21: &[i32];
let _22: &i32;
let mut _27: &[i32; 10];
}
scope 6 {
debug multiple_borrow => _22;
debug multiple_borrow => _23;
}
}
}
@ -59,8 +60,8 @@
_2 = const 5_u8;
_1 = &mut _2;
StorageLive(_3);
_28 = const debuginfo::promoted[2];
_3 = &((*_28).0: u8);
_29 = const debuginfo::promoted[2];
_3 = &((*_29).0: u8);
- StorageLive(_5);
- _5 = &(*_1);
- StorageLive(_6);
@ -76,8 +77,8 @@
bb2: {
StorageLive(_9);
_27 = const debuginfo::promoted[1];
_9 = &(((*_27) as Some).0: i32);
_28 = const debuginfo::promoted[1];
_9 = &(((*_28) as Some).0: i32);
- _6 = const ();
StorageDead(_9);
goto -> bb4;
@ -92,11 +93,11 @@
StorageDead(_7);
- StorageDead(_6);
- StorageLive(_10);
- StorageLive(_11);
StorageLive(_11);
- StorageLive(_12);
StorageLive(_13);
_26 = const debuginfo::promoted[0];
_13 = &(*_26);
_27 = const debuginfo::promoted[0];
_13 = &(*_27);
StorageLive(_15);
_15 = RangeFull;
- _12 = <[i32; 10] as Index<RangeFull>>::index(move _13, move _15) -> [return: bb5, unwind continue];
@ -106,28 +107,28 @@
bb5: {
StorageDead(_15);
StorageDead(_13);
- _11 = &(*_12);
- _16 = Len((*_11));
+ _16 = Len((*_12));
_17 = const 3_usize;
_18 = Ge(move _16, move _17);
switchInt(move _18) -> [0: bb7, otherwise: bb6];
_11 = &(*_12);
_17 = PtrMetadata(copy _11);
_16 = move _17;
_18 = const 3_usize;
_19 = Ge(move _16, move _18);
switchInt(move _19) -> [0: bb7, otherwise: bb6];
}
bb6: {
StorageLive(_19);
- _19 = &(*_11)[1 of 3];
+ _19 = &(*_12)[1 of 3];
StorageLive(_20);
- _20 = &(*_11)[2:-1];
+ _20 = &(*_12)[2:-1];
- _20 = &(*_11)[1 of 3];
+ _20 = &(*_12)[1 of 3];
StorageLive(_21);
- _21 = &(*_11)[-1 of 3];
- _21 = &(*_11)[2:-1];
+ _21 = &(*_12)[2:-1];
StorageLive(_22);
- _22 = &(*_11)[-1 of 3];
- _10 = const ();
+ _21 = &(*_12)[-1 of 3];
+ _22 = &(*_12)[-1 of 3];
StorageDead(_22);
StorageDead(_21);
StorageDead(_20);
StorageDead(_19);
goto -> bb8;
}
@ -138,21 +139,21 @@
bb8: {
- StorageDead(_12);
- StorageDead(_11);
StorageDead(_11);
- StorageDead(_10);
StorageLive(_22);
StorageLive(_23);
StorageLive(_24);
StorageLive(_25);
_25 = T(const 6_u8);
_24 = &mut (_25.0: u8);
StorageLive(_26);
_26 = T(const 6_u8);
_25 = &mut (_26.0: u8);
_24 = &_25;
_23 = &_24;
_22 = &_23;
_0 = const ();
StorageDead(_26);
StorageDead(_25);
StorageDead(_24);
StorageDead(_23);
StorageDead(_22);
- StorageDead(_5);
StorageDead(_3);
StorageDead(_2);