Move Place::elem methods and friends to TyCtxt

This commit is contained in:
Santiago Pastorino 2019-10-20 21:04:59 -04:00
parent d32c2865d6
commit 180fc413fb
No known key found for this signature in database
GPG Key ID: 88C941CDA1D46432
13 changed files with 139 additions and 124 deletions

View File

@ -1857,51 +1857,6 @@ impl<'tcx> Place<'tcx> {
}
}
pub fn field(self, f: Field, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Field(f, ty), tcx)
}
pub fn deref(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Deref, tcx)
}
pub fn downcast(
self,
adt_def: &'tcx AdtDef,
variant_index: VariantIdx,
tcx: TyCtxt<'tcx>,
) -> Place<'tcx> {
self.elem(
ProjectionElem::Downcast(
Some(adt_def.variants[variant_index].ident.name),
variant_index,
),
tcx,
)
}
pub fn downcast_unnamed(self, variant_index: VariantIdx, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Downcast(None, variant_index), tcx)
}
pub fn index(self, index: Local, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Index(index), tcx)
}
/// This method copies `Place`'s projection, add an element and reintern it. Should not be used
/// to build a full `Place` it's just a convenient way to grab a projection and modify it in
/// flight.
// FIXME: It may be a better idea to move all these methods to `PlaceBuilder`
pub fn elem(self, elem: PlaceElem<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
let mut projection = self.projection.to_vec();
projection.push(elem);
Place {
base: self.base,
projection: tcx.intern_place_elems(&projection),
}
}
/// Returns `true` if this `Place` contains a `Deref` projection.
///
/// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the

View File

@ -21,7 +21,7 @@ use crate::middle::cstore::EncodedMetadata;
use crate::middle::lang_items;
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use crate::middle::stability;
use crate::mir::{Body, interpret, PlaceElem, ProjectionKind, Promoted};
use crate::mir::{Body, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::mir::interpret::{ConstValue, Allocation, Scalar};
use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst};
use crate::ty::ReprOptions;
@ -2597,6 +2597,48 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_ty(Opaque(def_id, substs))
}
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Field(f, ty))
}
pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Deref)
}
pub fn mk_place_downcast(
self,
place: Place<'tcx>,
adt_def: &'tcx AdtDef,
variant_index: VariantIdx,
) -> Place<'tcx> {
self.mk_place_elem(
place,
PlaceElem::Downcast(Some(adt_def.variants[variant_index].ident.name), variant_index),
)
}
pub fn mk_place_downcast_unnamed(
self,
place: Place<'tcx>,
variant_index: VariantIdx,
) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
}
pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Index(index))
}
/// This method copies `Place`'s projection, add an element and reintern it. Should not be used
/// to build a full `Place` it's just a convenient way to grab a projection and modify it in
/// flight.
pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
let mut projection = place.projection.to_vec();
projection.push(elem);
Place { base: place.base, projection: self.intern_place_elems(&projection) }
}
pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
-> &'tcx List<ExistentialPredicate<'tcx>> {
assert!(!eps.is_empty());

View File

@ -139,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// initialize the box contents:
unpack!(
block = this.into(
&Place::from(result).deref(this.hir.tcx()),
&this.hir.tcx().mk_place_deref(Place::from(result)),
block, value
)
);
@ -296,10 +296,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.zip(field_types.into_iter())
.map(|(n, ty)| match fields_map.get(&n) {
Some(v) => v.clone(),
None => this.consume_by_copy_or_move(base.clone().field(
None => this.consume_by_copy_or_move(this.hir.tcx().mk_place_field(
base.clone(),
n,
ty,
this.hir.tcx(),
)),
})
.collect()
@ -402,8 +402,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let val_fld = Field::new(0);
let of_fld = Field::new(1);
let val = result_value.clone().field(val_fld, ty, self.hir.tcx());
let of = result_value.field(of_fld, bool_ty, self.hir.tcx());
let tcx = self.hir.tcx();
let val = tcx.mk_place_field(result_value.clone(), val_fld, ty);
let of = tcx.mk_place_field(result_value, of_fld, bool_ty);
let err = PanicInfo::Overflow(op);

View File

@ -235,7 +235,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
});
let ptr_temp = Place::from(ptr_temp);
let block = unpack!(this.into(&ptr_temp, block, ptr));
this.into(&ptr_temp.deref(this.hir.tcx()), block, val)
this.into(&this.hir.tcx().mk_place_deref(ptr_temp), block, val)
} else {
let args: Vec<_> = args
.into_iter()

View File

@ -166,7 +166,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
});
if irrefutable {
let place = match_pair.place.downcast(adt_def, variant_index, tcx);
let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index);
candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
Ok(())
} else {
@ -191,7 +191,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
PatKind::Deref { ref subpattern } => {
let place = match_pair.place.deref(tcx);
let place = tcx.mk_place_deref(match_pair.place);
candidate.match_pairs.push(MatchPair::new(place, subpattern));
Ok(())
}

View File

@ -743,23 +743,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidate: &mut Candidate<'pat, 'tcx>,
) {
let match_pair = candidate.match_pairs.remove(match_pair_index);
let tcx = self.hir.tcx();
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
// we want to create a set of derived match-patterns like
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
let elem = ProjectionElem::Downcast(
Some(adt_def.variants[variant_index].ident.name), variant_index);
let downcast_place = match_pair.place.elem(elem, self.hir.tcx()); // `(x as Variant)`
let consequent_match_pairs =
subpatterns.iter()
.map(|subpattern| {
// e.g., `(x as Variant).0`
let place = downcast_place.clone().field(subpattern.field,
subpattern.pattern.ty,
self.hir.tcx());
// e.g., `(x as Variant).0 @ P1`
MatchPair::new(place, &subpattern.pattern)
});
let downcast_place = tcx.mk_place_elem(match_pair.place, elem); // `(x as Variant)`
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
// e.g., `(x as Variant).0`
let place =
tcx.mk_place_field(downcast_place.clone(), subpattern.field, subpattern.pattern.ty);
// e.g., `(x as Variant).0 @ P1`
MatchPair::new(place, &subpattern.pattern)
});
candidate.match_pairs.extend(consequent_match_pairs);
}

View File

@ -6,18 +6,22 @@ use std::u32;
use std::convert::TryInto;
impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn field_match_pairs<'pat>(&mut self,
place: Place<'tcx>,
subpatterns: &'pat [FieldPat<'tcx>])
-> Vec<MatchPair<'pat, 'tcx>> {
subpatterns.iter()
.map(|fieldpat| {
let place = place.clone().field(fieldpat.field,
fieldpat.pattern.ty,
self.hir.tcx());
MatchPair::new(place, &fieldpat.pattern)
})
.collect()
pub fn field_match_pairs<'pat>(
&mut self,
place: Place<'tcx>,
subpatterns: &'pat [FieldPat<'tcx>],
) -> Vec<MatchPair<'pat, 'tcx>> {
subpatterns
.iter()
.map(|fieldpat| {
let place = self.hir.tcx().mk_place_field(
place.clone(),
fieldpat.field,
fieldpat.pattern.ty,
);
MatchPair::new(place, &fieldpat.pattern)
})
.collect()
}
pub fn prefix_slice_suffix<'pat>(&mut self,
@ -28,6 +32,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
suffix: &'pat [Pat<'tcx>]) {
let min_length = prefix.len() + suffix.len();
let min_length = min_length.try_into().unwrap();
let tcx = self.hir.tcx();
match_pairs.extend(
prefix.iter()
@ -38,16 +43,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
min_length,
from_end: false,
};
let place = place.clone().elem(elem, self.hir.tcx());
let place = tcx.mk_place_elem(place.clone(), elem);
MatchPair::new(place, subpattern)
})
);
if let Some(subslice_pat) = opt_slice {
let subslice = place.clone().elem(ProjectionElem::Subslice {
let subslice = tcx.mk_place_elem(place.clone(),ProjectionElem::Subslice {
from: prefix.len() as u32,
to: suffix.len() as u32
}, self.hir.tcx());
});
match_pairs.push(MatchPair::new(subslice, subslice_pat));
}
@ -61,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
min_length,
from_end: true,
};
let place = place.clone().elem(elem, self.hir.tcx());
let place = tcx.mk_place_elem(place.clone(), elem);
MatchPair::new(place, subpattern)
})
);

View File

@ -274,7 +274,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
// Box starts out uninitialized - need to create a separate
// move-path for the interior so it will be separate from
// the exterior.
self.create_move_path(&place.clone().deref(self.builder.tcx));
self.create_move_path(&self.builder.tcx.mk_place_deref(place.clone()));
self.gather_init(place.as_ref(), InitKind::Shallow);
} else {
self.gather_init(place.as_ref(), InitKind::Deep);

View File

@ -231,7 +231,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
tcx,
param_env
};
let dropee = dropee_ptr.deref(tcx);
let dropee = tcx.mk_place_deref(dropee_ptr);
let resume_block = elaborator.patch.resume_block();
elaborate_drops::elaborate_drop(
&mut elaborator,
@ -312,7 +312,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env, builder.span);
let dest = Place::return_place();
let src = Place::from(Local::new(1+0)).deref(tcx);
let src = tcx.mk_place_deref(Place::from(Local::new(1+0)));
match self_ty.kind {
_ if is_copy => builder.copy_shim(),
@ -415,7 +415,7 @@ impl CloneShimBuilder<'tcx> {
}
fn copy_shim(&mut self) {
let rcvr = Place::from(Local::new(1+0)).deref(self.tcx);
let rcvr = self.tcx.mk_place_deref(Place::from(Local::new(1+0)));
let ret_statement = self.make_statement(
StatementKind::Assign(
box(
@ -561,8 +561,8 @@ impl CloneShimBuilder<'tcx> {
// BB #2
// `dest[i] = Clone::clone(src[beg])`;
// Goto #3 if ok, #5 if unwinding happens.
let dest_field = dest.clone().index(beg, self.tcx);
let src_field = src.index(beg, self.tcx);
let dest_field = self.tcx.mk_place_index(dest.clone(), beg);
let src_field = self.tcx.mk_place_index(src, beg);
self.make_clone_call(dest_field, src_field, ty, BasicBlock::new(3),
BasicBlock::new(5));
@ -616,7 +616,7 @@ impl CloneShimBuilder<'tcx> {
// BB #7 (cleanup)
// `drop(dest[beg])`;
self.block(vec![], TerminatorKind::Drop {
location: dest.index(beg, self.tcx),
location: self.tcx.mk_place_index(dest, beg),
target: BasicBlock::new(8),
unwind: None,
}, true);
@ -648,9 +648,9 @@ impl CloneShimBuilder<'tcx> {
let mut previous_field = None;
for (i, ity) in tys.enumerate() {
let field = Field::new(i);
let src_field = src.clone().field(field, ity, self.tcx);
let src_field = self.tcx.mk_place_field(src.clone(), field, ity);
let dest_field = dest.clone().field(field, ity, self.tcx);
let dest_field = self.tcx.mk_place_field(dest.clone(), field, ity);
// #(2i + 1) is the cleanup block for the previous clone operation
let cleanup_block = self.block_index_offset(1);
@ -721,14 +721,14 @@ fn build_call_shim<'tcx>(
let rcvr = match rcvr_adjustment {
Adjustment::Identity => Operand::Move(rcvr_l),
Adjustment::Deref => Operand::Copy(rcvr_l.deref(tcx)),
Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_l)),
Adjustment::DerefMove => {
// fn(Self, ...) -> fn(*mut Self, ...)
let arg_ty = local_decls[rcvr_arg].ty;
debug_assert!(tcx.generics_of(def_id).has_self && arg_ty == tcx.types.self_param);
local_decls[rcvr_arg].ty = tcx.mk_mut_ptr(arg_ty);
Operand::Move(rcvr_l.deref(tcx))
Operand::Move(tcx.mk_place_deref(rcvr_l))
}
Adjustment::RefMut => {
// let rcvr = &mut rcvr;
@ -772,7 +772,7 @@ fn build_call_shim<'tcx>(
if let Some(untuple_args) = untuple_args {
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
let arg_place = Place::from(Local::new(1+1));
Operand::Move(arg_place.field(Field::new(i), *ity, tcx))
Operand::Move(tcx.mk_place_field(arg_place, Field::new(i), *ity))
}));
} else {
args.extend((1..sig.inputs().len()).map(|i| {

View File

@ -246,7 +246,7 @@ impl TransformVisitor<'tcx> {
// Create a Place referencing a generator struct field
fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
let self_place = Place::from(self_arg());
let base = self_place.downcast_unnamed(variant_index, self.tcx);
let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index);
let mut projection = base.projection.to_vec();
projection.push(ProjectionElem::Field(Field::new(idx), ty));

View File

@ -461,7 +461,7 @@ impl Inliner<'tcx> {
};
caller_body[callsite.bb]
.statements.push(stmt);
tmp.deref(self.tcx)
self.tcx.mk_place_deref(tmp)
} else {
destination.0
};
@ -560,10 +560,10 @@ impl Inliner<'tcx> {
let tuple_tmp_args =
tuple_tys.iter().enumerate().map(|(i, ty)| {
// This is e.g., `tuple_tmp.0` in our example above.
let tuple_field = Operand::Move(tuple.clone().field(
let tuple_field = Operand::Move(tcx.mk_place_field(
tuple.clone(),
Field::new(i),
ty.expect_ty(),
tcx,
));
// Spill to a local to make e.g., `tmp0`.

View File

@ -30,7 +30,7 @@ pub fn expand_aggregate<'tcx>(
},
source_info,
});
lhs = lhs.downcast(adt_def, variant_index, tcx);
lhs = tcx.mk_place_downcast(lhs, adt_def, variant_index);
}
active_field_index
}
@ -59,15 +59,15 @@ pub fn expand_aggregate<'tcx>(
// FIXME(eddyb) `offset` should be u64.
let offset = i as u32;
assert_eq!(offset as usize, i);
lhs.clone().elem(ProjectionElem::ConstantIndex {
tcx.mk_place_elem(lhs.clone(), ProjectionElem::ConstantIndex {
offset,
// FIXME(eddyb) `min_length` doesn't appear to be used.
min_length: offset + 1,
from_end: false
}, tcx)
})
} else {
let field = Field::new(active_field_index.unwrap_or(i));
lhs.clone().field(field, ty, tcx)
tcx.mk_place_field(lhs.clone(), field, ty)
};
Statement {
source_info,

View File

@ -200,13 +200,14 @@ where
variant.fields.iter().enumerate().map(|(i, f)| {
let field = Field::new(i);
let subpath = self.elaborator.field_subpath(variant_path, field);
let tcx = self.tcx();
assert_eq!(self.elaborator.param_env().reveal, Reveal::All);
let field_ty = self.tcx().normalize_erasing_regions(
let field_ty = tcx.normalize_erasing_regions(
self.elaborator.param_env(),
f.ty(self.tcx(), substs),
f.ty(tcx, substs),
);
(base_place.clone().field(field, field_ty, self.tcx()), subpath)
(tcx.mk_place_field(base_place.clone(), field, field_ty), subpath)
}).collect()
}
@ -323,7 +324,7 @@ where
debug!("open_drop_for_tuple({:?}, {:?})", self, tys);
let fields = tys.iter().enumerate().map(|(i, &ty)| {
(self.place.clone().field(Field::new(i), ty, self.tcx()),
(self.tcx().mk_place_field(self.place.clone(), Field::new(i), ty),
self.elaborator.field_subpath(self.path, Field::new(i)))
}).collect();
@ -334,7 +335,7 @@ where
fn open_drop_for_box(&mut self, adt: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>) -> BasicBlock {
debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs);
let interior = self.place.clone().deref(self.tcx());
let interior = self.tcx().mk_place_deref(self.place.clone());
let interior_path = self.elaborator.deref_subpath(self.path);
let succ = self.succ; // FIXME(#43234)
@ -406,14 +407,19 @@ where
};
let mut have_otherwise = false;
let tcx = self.tcx();
for (variant_index, discr) in adt.discriminants(self.tcx()) {
for (variant_index, discr) in adt.discriminants(tcx) {
let subpath = self.elaborator.downcast_subpath(
self.path, variant_index);
if let Some(variant_path) = subpath {
let base_place = self.place.clone().elem(
ProjectionElem::Downcast(Some(adt.variants[variant_index].ident.name),
variant_index), self.tcx());
let base_place = tcx.mk_place_elem(
self.place.clone(),
ProjectionElem::Downcast(
Some(adt.variants[variant_index].ident.name),
variant_index,
),
);
let fields = self.move_paths_for_fields(
&base_place,
variant_path,
@ -586,7 +592,7 @@ where
BorrowKind::Mut { allow_two_phase_borrow: false },
Place {
base: PlaceBase::Local(cur),
projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Deref]),
projection: tcx.intern_place_elems(&vec![ProjectionElem::Deref]),
}
),
Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one))
@ -594,7 +600,7 @@ where
(Rvalue::Ref(
tcx.lifetimes.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
self.place.clone().index(cur, self.tcx())),
tcx.mk_place_index(self.place.clone(), cur)),
Rvalue::BinaryOp(BinOp::Add, move_(&Place::from(cur)), one))
};
@ -627,7 +633,7 @@ where
let loop_block = self.elaborator.patch().new_block(loop_block);
self.elaborator.patch().patch_terminator(drop_block, TerminatorKind::Drop {
location: ptr.clone().deref(tcx),
location: tcx.mk_place_deref(ptr.clone()),
target: loop_block,
unwind: unwind.into_option()
});
@ -644,18 +650,27 @@ where
// ptr_based_loop
// }
let tcx = self.tcx();
if let Some(size) = opt_size {
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,
min_length: size,
from_end: false
}, self.tcx()),
self.elaborator.array_subpath(self.path, i, size))
}).collect();
let fields: Vec<(Place<'tcx>, Option<D::Path>)> = (0..size)
.map(|i| {
(
tcx.mk_place_elem(
self.place.clone(),
ProjectionElem::ConstantIndex {
offset: i,
min_length: size,
from_end: false,
},
),
self.elaborator.array_subpath(self.path, i, size),
)
})
.collect();
if fields.iter().any(|(_,path)| path.is_some()) {
let (succ, unwind) = self.drop_ladder_bottom();
@ -664,7 +679,6 @@ where
}
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
let tcx = self.tcx();
let elem_size = &Place::from(self.new_temp(tcx.types.usize));
let len = &Place::from(self.new_temp(tcx.types.usize));
@ -900,8 +914,8 @@ where
);
let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
let field = Field::new(i);
let field_ty = f.ty(self.tcx(), substs);
Operand::Move(self.place.clone().field(field, field_ty, self.tcx()))
let field_ty = f.ty(tcx, substs);
Operand::Move(tcx.mk_place_field(self.place.clone(), field, field_ty))
}).collect();
let call = TerminatorKind::Call {