use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Ty, TyCtxt};
+
+/// Constructs the types used when accessing a Box's pointer
+pub fn build_ptr_tys<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ pointee: Ty<'tcx>,
+ unique_did: DefId,
+ nonnull_did: DefId,
+) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
+ let substs = tcx.intern_substs(&[pointee.into()]);
+ let unique_ty = tcx.bound_type_of(unique_did).subst(tcx, substs);
+ let nonnull_ty = tcx.bound_type_of(nonnull_did).subst(tcx, substs);
+ let ptr_ty = tcx.mk_imm_ptr(pointee);
+
+ (unique_ty, nonnull_ty, ptr_ty)
+}
+
+// Constructs the projection needed to access a Box's pointer
+pub fn build_projection<'tcx>(
+ unique_ty: Ty<'tcx>,
+ nonnull_ty: Ty<'tcx>,
+ ptr_ty: Ty<'tcx>,
+) -> [PlaceElem<'tcx>; 3] {
+ [
+ PlaceElem::Field(Field::new(0), unique_ty),
+ PlaceElem::Field(Field::new(0), nonnull_ty),
+ PlaceElem::Field(Field::new(0), ptr_ty),
+ ]
+}
struct ElaborateBoxDerefVisitor<'tcx, 'a> {
tcx: TyCtxt<'tcx>,
if place.projection.first() == Some(&PlaceElem::Deref) && base_ty.is_box() {
let source_info = self.local_decls[place.local].source_info;
- let substs = tcx.intern_substs(&[base_ty.boxed_ty().into()]);
- let unique_ty = tcx.bound_type_of(self.unique_did).subst(tcx, substs);
- let nonnull_ty = tcx.bound_type_of(self.nonnull_did).subst(tcx, substs);
- let ptr_ty = tcx.mk_imm_ptr(base_ty.boxed_ty());
+ let (unique_ty, nonnull_ty, ptr_ty) =
+ build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did);
let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
self.local_decls.push(LocalDecl::new(ptr_ty, source_info.span));
self.patch.add_assign(
location,
Place::from(ptr_local),
- Rvalue::Use(Operand::Copy(Place::from(place.local).project_deeper(
- &[
- PlaceElem::Field(Field::new(0), unique_ty),
- PlaceElem::Field(Field::new(0), nonnull_ty),
- PlaceElem::Field(Field::new(0), ptr_ty),
- ],
- tcx,
- ))),
+ Rvalue::Use(Operand::Copy(
+ Place::from(place.local)
+ .project_deeper(&build_projection(unique_ty, nonnull_ty, ptr_ty), tcx),
+ )),
);
place.local = ptr_local;
let nonnull_did = nonnull_def.non_enum_variant().fields[0].did;
- let substs = tcx.intern_substs(&[box_ty.boxed_ty().into()]);
- let unique_ty = tcx.bound_type_of(unique_did).subst(tcx, substs);
- let nonnull_ty = tcx.bound_type_of(nonnull_did).subst(tcx, substs);
- let ptr_ty = tcx.mk_imm_ptr(box_ty.boxed_ty());
+ let (unique_ty, nonnull_ty, ptr_ty) =
+ crate::elaborate_box_derefs::build_ptr_tys(
+ tcx,
+ box_ty.boxed_ty(),
+ unique_did,
+ nonnull_did,
+ );
let ptr_local = body.local_decls.push(LocalDecl::new(ptr_ty, body.span));
kind: StatementKind::Assign(Box::new((
Place::from(ptr_local),
Rvalue::Use(Operand::Copy(box_place.project_deeper(
- &[
- PlaceElem::Field(Field::new(0), unique_ty),
- PlaceElem::Field(Field::new(0), nonnull_ty),
- PlaceElem::Field(Field::new(0), ptr_ty),
- ],
+ &crate::elaborate_box_derefs::build_projection(
+ unique_ty, nonnull_ty, ptr_ty,
+ ),
tcx,
))),
))),