use rustc_data_structures::indexed_vec::Idx;
use crate::util::patch::MirPatch;
-use std::u32;
+use std::convert::TryInto;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum DropFlagState {
type Path : Copy + fmt::Debug;
fn patch(&mut self) -> &mut MirPatch<'tcx>;
- fn mir(&self) -> &'a Mir<'tcx>;
+ fn mir(&self) -> &'a Body<'tcx>;
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
fn param_env(&self) -> ty::ParamEnv<'tcx>;
let ty = self.place_ty(self.place);
let substs = tcx.mk_substs_trait(ty, &[]);
- let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
+ let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut {
ty,
mutbl: hir::Mutability::MutMutable
});
let result = BasicBlockData {
statements: vec![self.assign(
&Place::Base(PlaceBase::Local(ref_place)),
- Rvalue::Ref(tcx.types.re_erased,
+ Rvalue::Ref(tcx.lifetimes.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
self.place.clone())
)],
self.elaborator.patch().new_block(result)
}
- /// create a loop that drops an array:
- ///
-
+ /// Create a loop that drops an array:
///
+ /// ```text
/// loop-block:
/// can_go = cur == length_or_end
/// if can_go then succ else drop-block
/// cur = cur + 1
/// }
/// drop(ptr)
- fn drop_loop(&mut self,
- succ: BasicBlock,
- cur: Local,
- length_or_end: &Place<'tcx>,
- ety: Ty<'tcx>,
- unwind: Unwind,
- ptr_based: bool)
- -> BasicBlock
- {
+ /// ```
+ fn drop_loop(
+ &mut self,
+ succ: BasicBlock,
+ cur: Local,
+ length_or_end: &Place<'tcx>,
+ ety: Ty<'tcx>,
+ unwind: Unwind,
+ ptr_based: bool,
+ ) -> BasicBlock {
let copy = |place: &Place<'tcx>| Operand::Copy(place.clone());
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
let tcx = self.tcx();
- let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
+ let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut {
ty: ety,
mutbl: hir::Mutability::MutMutable
});
let one = self.constant_usize(1);
let (ptr_next, cur_next) = if ptr_based {
(Rvalue::Ref(
- tcx.types.re_erased,
+ tcx.lifetimes.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
Place::Projection(Box::new(Projection {
base: Place::Base(PlaceBase::Local(cur)),
elem: ProjectionElem::Deref,
}))
),
- Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one))
+ Rvalue::BinaryOp(BinOp::Offset, move_(&Place::Base(PlaceBase::Local(cur))), one))
} else {
(Rvalue::Ref(
- tcx.types.re_erased,
+ tcx.lifetimes.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
self.place.clone().index(cur)),
- Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one))
+ Rvalue::BinaryOp(BinOp::Add, move_(&Place::Base(PlaceBase::Local(cur))), one))
};
let drop_block = BasicBlockData {
// }
if let Some(size) = opt_size {
- assert!(size <= (u32::MAX as u64),
- "move out check doesn't implemented for array bigger then u32");
- let size = size as u32;
+ let size: u32 = size.try_into().unwrap_or_else(|_| {
+ bug!("move out check isn't implemented for array sizes bigger than u32::MAX");
+ });
let fields: Vec<(Place<'tcx>, Option<D::Path>)> = (0..size).map(|i| {
(self.place.clone().elem(ProjectionElem::ConstantIndex{
offset: i,
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
let tcx = self.tcx();
- let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
- let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
+ let elem_size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
+ let len = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
+
+ static USIZE_SWITCH_ZERO: &[u128] = &[0];
+
let base_block = BasicBlockData {
statements: vec![
- self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
- self.assign(size_is_zero, Rvalue::BinaryOp(BinOp::Eq,
- move_(size),
- self.constant_usize(0)))
+ self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
+ self.assign(len, Rvalue::Len(self.place.clone())),
],
is_cleanup: self.unwind.is_cleanup(),
terminator: Some(Terminator {
source_info: self.source_info,
- kind: TerminatorKind::if_(
- tcx,
- move_(size_is_zero),
- self.drop_loop_pair(ety, false),
- self.drop_loop_pair(ety, true)
- )
+ kind: TerminatorKind::SwitchInt {
+ discr: move_(elem_size),
+ switch_ty: tcx.types.usize,
+ values: From::from(USIZE_SWITCH_ZERO),
+ targets: vec![
+ self.drop_loop_pair(ety, false, len.clone()),
+ self.drop_loop_pair(ety, true, len.clone()),
+ ],
+ },
})
};
self.elaborator.patch().new_block(base_block)
}
- // create a pair of drop-loops of `place`, which drops its contents
- // even in the case of 1 panic. If `ptr_based`, create a pointer loop,
- // otherwise create an index loop.
- fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock {
+ /// Ceates a pair of drop-loops of `place`, which drops its contents, even
+ /// in the case of 1 panic. If `ptr_based`, creates a pointer loop,
+ /// otherwise create an index loop.
+ fn drop_loop_pair(
+ &mut self,
+ ety: Ty<'tcx>,
+ ptr_based: bool,
+ length: Place<'tcx>,
+ ) -> BasicBlock {
debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based);
let tcx = self.tcx();
let iter_ty = if ptr_based {
};
let cur = self.new_temp(iter_ty);
- let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
let length_or_end = if ptr_based {
// FIXME check if we want to make it return a `Place` directly
// if all use sites want a `Place::Base` anyway.
ptr_based)
});
- let succ = self.succ; // FIXME(#43234)
let loop_block = self.drop_loop(
- succ,
+ self.succ,
cur,
&length_or_end,
ety,
ptr_based);
let cur = Place::Base(PlaceBase::Local(cur));
- let zero = self.constant_usize(0);
- let mut drop_block_stmts = vec![];
- drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone())));
- if ptr_based {
+ let drop_block_stmts = if ptr_based {
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty)));
// tmp = &mut P;
// cur = tmp as *mut T;
// end = Offset(cur, len);
- drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref(
- tcx.types.re_erased,
- BorrowKind::Mut { allow_two_phase_borrow: false },
- self.place.clone()
- )));
- drop_block_stmts.push(self.assign(&cur, Rvalue::Cast(
- CastKind::Misc, Operand::Move(tmp), iter_ty
- )));
- drop_block_stmts.push(self.assign(&length_or_end,
- Rvalue::BinaryOp(BinOp::Offset,
- Operand::Copy(cur), Operand::Move(length)
- )));
+ vec![
+ self.assign(&tmp, Rvalue::Ref(
+ tcx.lifetimes.re_erased,
+ BorrowKind::Mut { allow_two_phase_borrow: false },
+ self.place.clone()
+ )),
+ self.assign(
+ &cur,
+ Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty),
+ ),
+ self.assign(
+ &length_or_end,
+ Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)
+ )),
+ ]
} else {
- // index = 0 (length already pushed)
- drop_block_stmts.push(self.assign(&cur, Rvalue::Use(zero)));
- }
+ // cur = 0 (length already pushed)
+ let zero = self.constant_usize(0);
+ vec![self.assign(&cur, Rvalue::Use(zero))]
+ };
let drop_block = self.elaborator.patch().new_block(BasicBlockData {
statements: drop_block_stmts,
is_cleanup: unwind.is_cleanup(),
// FIXME(#34708): handle partially-dropped array/slice elements.
let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind);
- self.drop_flag_test_block(reset_block, succ, unwind)
+ self.drop_flag_test_block(reset_block, self.succ, unwind)
}
/// The slow-path - create an "open", elaborated drop for a type
span: self.source_info.span,
ty: self.tcx().types.usize,
user_ty: None,
- literal: self.tcx().mk_const(
- ty::Const::from_usize(self.tcx(), val.into())
- ),
+ literal: ty::Const::from_usize(self.tcx(), val.into()),
})
}