Intern place projection

上级 a19aed22
......@@ -15,8 +15,7 @@
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{
self, AdtDef, CanonicalUserTypeAnnotations, Region, Ty, TyCtxt,
UserTypeAnnotationIndex,
self, AdtDef, CanonicalUserTypeAnnotations, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex,
};
use polonius_engine::Atom;
......@@ -1712,15 +1711,17 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
/// A path to a value; something that can be evaluated without
/// changing or disturbing program state.
#[derive(
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable,
)]
pub struct Place<'tcx> {
pub base: PlaceBase<'tcx>,
/// projection out of a place (access a field, deref a pointer, etc)
pub projection: Box<[PlaceElem<'tcx>]>,
pub projection: &'tcx List<PlaceElem<'tcx>>,
}
impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {}
#[derive(
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
)]
......@@ -1848,50 +1849,56 @@ pub struct PlaceRef<'a, 'tcx> {
}
impl<'tcx> Place<'tcx> {
// FIXME change this back to a const when projection is a shared slice.
//
// pub const RETURN_PLACE: Place<'tcx> = Place {
// base: PlaceBase::Local(RETURN_PLACE),
// projection: &[],
// };
// FIXME change this to a const fn by also making List::empty a const fn.
pub fn return_place() -> Place<'tcx> {
Place {
base: PlaceBase::Local(RETURN_PLACE),
projection: Box::new([]),
projection: List::empty(),
}
}
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Field(f, ty))
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) -> Place<'tcx> {
self.elem(ProjectionElem::Deref)
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) -> Place<'tcx> {
self.elem(ProjectionElem::Downcast(
Some(adt_def.variants[variant_index].ident.name),
variant_index,
))
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) -> Place<'tcx> {
self.elem(ProjectionElem::Downcast(None, variant_index))
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) -> Place<'tcx> {
self.elem(ProjectionElem::Index(index))
pub fn index(self, index: Local, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Index(index), tcx)
}
pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
// FIXME(spastorino): revisit this again once projection is not a Box<[T]> anymore
let mut projection = self.projection.into_vec();
/// 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: projection.into_boxed_slice(),
projection: tcx.intern_place_elems(&projection),
}
}
......@@ -1939,7 +1946,7 @@ impl From<Local> for Place<'_> {
fn from(local: Local) -> Self {
Place {
base: local.into(),
projection: Box::new([]),
projection: List::empty(),
}
}
}
......@@ -3190,6 +3197,17 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
folder.tcx().intern_place_elems(&v)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
}
}
impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Static {
......
......@@ -784,6 +784,8 @@ fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Locat
macro_rules! visit_place_fns {
(mut) => (
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
fn super_place(
&mut self,
place: &mut Place<'tcx>,
......@@ -793,19 +795,21 @@ fn super_place(
self.visit_place_base(&mut place.base, context, location);
if let Some(new_projection) = self.process_projection(&place.projection) {
place.projection = new_projection;
place.projection = self.tcx().intern_place_elems(&new_projection);
}
}
fn process_projection(
&mut self,
projection: &'a [PlaceElem<'tcx>],
) -> Option<Box<[PlaceElem<'tcx>]>> {
) -> Option<Vec<PlaceElem<'tcx>>> {
let mut projection = Cow::Borrowed(projection);
for i in 0..projection.len() {
if let Some(elem) = projection.get(i) {
if let Some(elem) = self.process_projection_elem(elem) {
// This converts the borrowed projection into `Cow::Owned(_)` and returns a
// clone of the projection so we can mutate and reintern later.
let vec = projection.to_mut();
vec[i] = elem;
}
......@@ -814,7 +818,7 @@ fn process_projection(
match projection {
Cow::Borrowed(_) => None,
Cow::Owned(vec) => Some(vec.into_boxed_slice()),
Cow::Owned(vec) => Some(vec),
}
}
......
......@@ -13,9 +13,9 @@
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
use std::hash::Hash;
use std::intrinsics;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::{self, List, Ty, TyCtxt};
use crate::ty::subst::SubstsRef;
use crate::mir::interpret::Allocation;
use crate::mir::{self, interpret::Allocation};
use syntax_pos::Span;
/// The shorthand encoding uses an enum's variant index `usize`
......@@ -218,6 +218,18 @@ pub fn decode_substs<D>(decoder: &mut D) -> Result<SubstsRef<'tcx>, D::Error>
Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
}
#[inline]
pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error>
where
D: TyDecoder<'tcx>,
{
let base: mir::PlaceBase<'tcx> = Decodable::decode(decoder)?;
let len = decoder.read_usize()?;
let projection: &'tcx List<mir::PlaceElem<'tcx>> =
decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
Ok(mir::Place { base, projection })
}
#[inline]
pub fn decode_region<D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
where
......@@ -413,6 +425,15 @@ fn specialized_decode(&mut self) -> Result<SubstsRef<'tcx>, Self::Error> {
}
}
impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(
&mut self
) -> Result<$crate::mir::Place<'tcx>, Self::Error> {
decode_place(self)
}
}
impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
......
......@@ -2711,6 +2711,11 @@ pub fn mk_substs<I: InternAs<[GenericArg<'tcx>],
iter.intern_with(|xs| self.intern_substs(xs))
}
pub fn mk_place_elems<I: InternAs<[PlaceElem<'tcx>],
&'tcx List<PlaceElem<'tcx>>>>(self, iter: I) -> I::Output {
iter.intern_with(|xs| self.intern_place_elems(xs))
}
pub fn mk_substs_trait(self,
self_ty: Ty<'tcx>,
rest: &[GenericArg<'tcx>])
......
......@@ -707,10 +707,12 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
_ => drop_span,
};
let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection);
if self.access_place_error_reported
.contains(&(Place {
base: root_place.base.clone(),
projection: root_place.projection.to_vec().into_boxed_slice(),
projection: root_place_projection,
}, borrow_span))
{
debug!(
......@@ -723,7 +725,7 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
self.access_place_error_reported
.insert((Place {
base: root_place.base.clone(),
projection: root_place.projection.to_vec().into_boxed_slice(),
projection: root_place_projection,
}, borrow_span));
if let StorageDeadOrDrop::Destructor(dropped_ty) =
......
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::mir::{Body, Location, PlaceElem, Promoted};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
......@@ -54,6 +54,10 @@ fn renumber_regions<T>(&mut self, value: &T) -> T
}
impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context);
......
......@@ -6,7 +6,7 @@
use crate::hair::*;
use rustc::mir::interpret::{PanicInfo::BoundsCheck};
use rustc::mir::*;
use rustc::ty::{CanonicalUserTypeAnnotation, Ty, Variance};
use rustc::ty::{CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance};
use rustc_index::vec::Idx;
......@@ -23,10 +23,10 @@ struct PlaceBuilder<'tcx> {
}
impl PlaceBuilder<'tcx> {
fn into_place(self) -> Place<'tcx> {
fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
Place {
base: self.base,
projection: self.projection.into_boxed_slice(),
projection: tcx.intern_place_elems(&self.projection),
}
}
......@@ -73,7 +73,7 @@ pub fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
let place_builder = unpack!(block = self.as_place_builder(block, expr));
block.and(place_builder.into_place())
block.and(place_builder.into_place(self.hir.tcx()))
}
/// This is used when constructing a compound `Place`, so that we can avoid creating
......@@ -96,7 +96,7 @@ pub fn as_read_only_place<M>(&mut self, mut block: BasicBlock, expr: M) -> Block
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
block.and(place_builder.into_place())
block.and(place_builder.into_place(self.hir.tcx()))
}
/// This is used when constructing a compound `Place`, so that we can avoid creating
......@@ -165,7 +165,7 @@ fn expr_as_place(
Mutability::Not,
));
let slice = place_builder.clone().into_place();
let slice = place_builder.clone().into_place(this.hir.tcx());
// bounds check:
let (len, lt) = (
this.temp(usize_ty.clone(), expr_span),
......@@ -225,7 +225,7 @@ fn expr_as_place(
}
);
let place = place_builder.clone().into_place();
let place = place_builder.clone().into_place(this.hir.tcx());
this.cfg.push(
block,
Statement {
......
......@@ -139,7 +139,7 @@ fn expr_as_rvalue(
// initialize the box contents:
unpack!(
block = this.into(
&Place::from(result).deref(),
&Place::from(result).deref(this.hir.tcx()),
block, value
)
);
......@@ -296,8 +296,13 @@ fn expr_as_rvalue(
.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(n, ty)),
}).collect()
None => this.consume_by_copy_or_move(base.clone().field(
n,
ty,
this.hir.tcx(),
)),
})
.collect()
} else {
field_names
.iter()
......@@ -397,8 +402,8 @@ pub fn build_binary_op(
let val_fld = Field::new(0);
let of_fld = Field::new(1);
let val = result_value.clone().field(val_fld, ty);
let of = result_value.field(of_fld, bool_ty);
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 err = PanicInfo::Overflow(op);
......
......@@ -235,7 +235,7 @@ pub fn into_expr(
});
let ptr_temp = Place::from(ptr_temp);
let block = unpack!(this.into(&ptr_temp, block, ptr));
this.into(&ptr_temp.deref(), block, val)
this.into(&ptr_temp.deref(this.hir.tcx()), block, val)
} else {
let args: Vec<_> = args
.into_iter()
......
......@@ -948,7 +948,7 @@ fn select_matched_candidates(
fake_borrows.insert(Place {
base: source.base.clone(),
projection: proj_base.to_vec().into_boxed_slice(),
projection: self.hir.tcx().intern_place_elems(proj_base),
});
}
}
......@@ -1488,7 +1488,7 @@ fn bind_and_guard_matched_candidate<'pat>(
BorrowKind::Shallow,
Place {
base: place.base.clone(),
projection: place.projection.to_vec().into_boxed_slice(),
projection: tcx.intern_place_elems(place.projection),
},
);
self.cfg.push_assign(
......
......@@ -166,7 +166,7 @@ fn simplify_match_pair<'pat>(&mut self,
}
});
if irrefutable {
let place = match_pair.place.downcast(adt_def, variant_index);
let place = match_pair.place.downcast(adt_def, variant_index, tcx);
candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
Ok(())
} else {
......@@ -191,7 +191,7 @@ fn simplify_match_pair<'pat>(&mut self,
}
PatKind::Deref { ref subpattern } => {
let place = match_pair.place.deref();
let place = match_pair.place.deref(tcx);
candidate.match_pairs.push(MatchPair::new(place, subpattern));
Ok(())
}
......
......@@ -749,13 +749,14 @@ fn candidate_after_variant_switch<'pat>(
// `(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); // `(x as Variant)`
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);
subpattern.pattern.ty,
self.hir.tcx());
// e.g., `(x as Variant).0 @ P1`
MatchPair::new(place, &subpattern.pattern)
});
......
......@@ -13,7 +13,8 @@ pub fn field_match_pairs<'pat>(&mut self,
subpatterns.iter()
.map(|fieldpat| {
let place = place.clone().field(fieldpat.field,
fieldpat.pattern.ty);
fieldpat.pattern.ty,
self.hir.tcx());
MatchPair::new(place, &fieldpat.pattern)
})
.collect()
......@@ -37,7 +38,7 @@ pub fn prefix_slice_suffix<'pat>(&mut self,
min_length,
from_end: false,
};
let place = place.clone().elem(elem);
let place = place.clone().elem(elem, self.hir.tcx());
MatchPair::new(place, subpattern)
})
);
......@@ -46,7 +47,7 @@ pub fn prefix_slice_suffix<'pat>(&mut self,
let subslice = place.clone().elem(ProjectionElem::Subslice {
from: prefix.len() as u32,
to: suffix.len() as u32
});
}, self.hir.tcx());
match_pairs.push(MatchPair::new(subslice, subslice_pat));
}
......@@ -60,7 +61,7 @@ pub fn prefix_slice_suffix<'pat>(&mut self,
min_length,
from_end: true,
};
let place = place.clone().elem(elem);
let place = place.clone().elem(elem, self.hir.tcx());
MatchPair::new(place, subpattern)
})
);
......
......@@ -114,7 +114,7 @@ fn move_path_for(&mut self, place: &Place<'tcx>) -> Result<MovePathIndex, MoveEr
BorrowedContent {
target_place: Place {
base: place.base.clone(),
projection: proj.to_vec().into_boxed_slice(),
projection: tcx.intern_place_elems(proj),
},
},
));
......@@ -172,7 +172,7 @@ fn move_path_for(&mut self, place: &Place<'tcx>) -> Result<MovePathIndex, MoveEr
Some(base),
Place {
base: place.base.clone(),
projection: proj.to_vec().into_boxed_slice(),
projection: tcx.intern_place_elems(proj),
},
);
ent.insert(path);
......@@ -274,7 +274,7 @@ fn gather_statement(&mut self, stmt: &Statement<'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.create_move_path(&place.clone().deref(self.builder.tcx));
self.gather_init(place.as_ref(), InitKind::Shallow);
} else {
self.gather_init(place.as_ref(), InitKind::Deep);
......
......@@ -117,7 +117,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
run_passes(tcx, &mut result, instance, None, MirPhase::Const, &[
&add_moves_for_packed_drops::AddMovesForPackedDrops,
&no_landing_pads::NoLandingPads,
&no_landing_pads::NoLandingPads::new(tcx),
&remove_noop_landing_pads::RemoveNoopLandingPads,
&simplify::SimplifyCfg::new("make_shim"),
&add_call_guards::CriticalCallEdges,
......@@ -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();
let dropee = dropee_ptr.deref(tcx);
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();
let src = Place::from(Local::new(1+0)).deref(tcx);
match self_ty.kind {
_ if is_copy => builder.copy_shim(),
......@@ -415,7 +415,7 @@ fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> {
}
fn copy_shim(&mut self) {
let rcvr = Place::from(Local::new(1+0)).deref();
let rcvr = Place::from(Local::new(1+0)).deref(self.tcx);
let ret_statement = self.make_statement(
StatementKind::Assign(
box(
......@@ -561,8 +561,8 @@ fn array_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, ty: Ty<'tcx>, len:
// BB #2
// `dest[i] = Clone::clone(src[beg])`;
// Goto #3 if ok, #5 if unwinding happens.
let dest_field = dest.clone().index(beg);
let src_field = src.index(beg);
let dest_field = dest.clone().index(beg, self.tcx);
let src_field = src.index(beg, self.tcx);
self.make_clone_call(dest_field, src_field, ty, BasicBlock::new(3),
BasicBlock::new(5));
......@@ -616,7 +616,7 @@ fn array_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, ty: Ty<'tcx>, len:
// BB #7 (cleanup)
// `drop(dest[beg])`;
self.block(vec![], TerminatorKind::Drop {
location: dest.index(beg),
location: dest.index(beg, self.tcx),
target: BasicBlock::new(8),
unwind: None,
}, true);
......@@ -648,9 +648,9 @@ fn tuple_like_shim<I>(&mut self, dest: Place<'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);
let src_field = src.clone().field(field, ity, self.tcx);
let dest_field = dest.clone().field(field, ity);
let dest_field = dest.clone().field(field, ity, self.tcx);
// #(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()),
Adjustment::Deref => Operand::Copy(rcvr_l.deref(tcx)),
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())
Operand::Move(rcvr_l.deref(tcx))
}
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))
Operand::Move(arg_place.field(Field::new(i), *ity, tcx))
}));
} else {
args.extend((1..sig.inputs().len()).map(|i| {
......@@ -901,6 +901,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> {
)),
AggregateKind::Adt(adt_def, variant_index, substs, None, None),
source_info,
tcx,
).collect();
let start_block = BasicBlockData {
......
......@@ -24,16 +24,22 @@
pub struct CleanupNonCodegenStatements;
pub struct DeleteNonCodegenStatements;
pub struct DeleteNonCodegenStatements<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
let mut delete = DeleteNonCodegenStatements;
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
let mut delete = DeleteNonCodegenStatements { tcx };
delete.visit_body(body);
}
}
impl<'tcx> MutVisitor<'tcx> for DeleteNonCodegenStatements {
impl<'tcx> MutVisitor<'tcx> for DeleteNonCodegenStatements<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_statement(&mut self,
statement: &mut Statement<'tcx>,
location: Location) {
......
......@@ -687,6 +687,10 @@ fn visit_local(
}
impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_constant(
&mut self,
constant: &mut Constant<'tcx>,
......
......@@ -126,7 +126,8 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<
}
}
changed = action.perform(body, &def_use_analysis, dest_local, location) || changed;
changed =
action.perform(body, &def_use_analysis, dest_local, location, tcx) || changed;
// FIXME(pcwalton): Update the use-def chains to delete the instructions instead of
// regenerating the chains.
break
......@@ -244,7 +245,8 @@ fn perform(self,
body: &mut Body<'tcx>,
def_use_analysis: &DefUseAnalysis,
dest_local: Local,
location: Location)
location: Location,
tcx: TyCtxt<'tcx>)
-> bool {
match self {
Action::PropagateLocalCopy(src_local) => {
......@@ -268,7 +270,7 @@ fn perform(self,
}
// Replace all uses of the destination local with the source local.
def_use_analysis.replace_all_defs_and_uses_with(dest_local, body, src_local);
def_use_analysis.replace_all_defs_and_uses_with(dest_local, body, src_local, tcx);
// Finally, zap the now-useless assignment instruction.
debug!(" Deleting assignment");
......@@ -292,7 +294,8 @@ fn perform(self,
// Replace all uses of the destination local with the constant.
let mut visitor = ConstantPropagationVisitor::new(dest_local,
src_constant);
src_constant,
tcx);
for dest_place_use in &dest_local_info.defs_and_uses {
visitor.visit_location(body, dest_place_use.location)
}
......@@ -324,21 +327,27 @@ fn perform(self,
struct ConstantPropagationVisitor<'tcx> {
dest_local: Local,
constant: Constant<'tcx>,
tcx: TyCtxt<'tcx>,
uses_replaced: usize,
}
impl<'tcx> ConstantPropagationVisitor<'tcx> {
fn new(dest_local: Local, constant: Constant<'tcx>)
fn new(dest_local: Local, constant: Constant<'tcx>, tcx: TyCtxt<'tcx>)
-> ConstantPropagationVisitor<'tcx> {
ConstantPropagationVisitor {
dest_local,
constant,
tcx,
uses_replaced: 0,
}
}
}
impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
self.super_operand(operand, location);
......
......@@ -45,6 +45,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<
}),
*kind,
source_info,
tcx,
))
});
}
......
......@@ -23,6 +23,10 @@ pub fn new(tcx: TyCtxt<'tcx>) -> Self {
}
impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
*ty = self.tcx.erase_regions(ty);
}
......
......@@ -74,12 +74,17 @@
pub struct StateTransform;
struct RenameLocalVisitor {
struct RenameLocalVisitor<'tcx> {
from: Local,
to: Local,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor {
impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_local(&mut self,
local: &mut Local,
_: PlaceContext,
......@@ -102,9 +107,15 @@ fn process_projection_elem(
}
}
struct DerefArgVisitor;
struct DerefArgVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
fn visit_local(&mut self,
local: &mut Local,
_: PlaceContext,
......@@ -119,8 +130,8 @@ fn visit_place(&mut self,
if place.base == PlaceBase::Local(self_arg()) {
replace_base(place, Place {
base: PlaceBase::Local(self_arg()),
projection: Box::new([ProjectionElem::Deref]),
});
projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Deref]),
}, self.tcx);
} else {
self.visit_place_base(&mut place.base, context, location);
......@@ -135,9 +146,14 @@ fn visit_place(&mut self,
struct PinArgVisitor<'tcx> {
ref_gen_ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_local(&mut self,
local: &mut Local,
_: PlaceContext,
......@@ -145,15 +161,19 @@ fn visit_local(&mut self,
assert_ne!(*local, self_arg());
}
fn visit_place(&mut self,
place: &mut Place<'tcx>,
context: PlaceContext,
location: Location) {
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
if place.base == PlaceBase::Local(self_arg()) {
replace_base(place, Place {
base: PlaceBase::Local(self_arg()),
projection: Box::new([ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]),
});
replace_base(
place,
Place {
base: PlaceBase::Local(self_arg()),
projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Field(
Field::new(0),
self.ref_gen_ty,
)]),
},
self.tcx,
);
} else {
self.visit_place_base(&mut place.base, context, location);
......@@ -166,13 +186,13 @@ fn visit_place(&mut self,
}
}
fn replace_base(place: &mut Place<'tcx>, new_base: Place<'tcx>) {
fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) {
place.base = new_base.base;
let mut new_projection = new_base.projection.to_vec();
new_projection.append(&mut place.projection.to_vec());
place.projection = new_projection.into_boxed_slice();
place.projection = tcx.intern_place_elems(&new_projection);
}
fn self_arg() -> Local {
......@@ -226,13 +246,13 @@ fn make_state(&self, idx: VariantIdx, val: Operand<'tcx>) -> Rvalue<'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);
let base = self_place.downcast_unnamed(variant_index, self.tcx);
let mut projection = base.projection.to_vec();
projection.push(ProjectionElem::Field(Field::new(idx), ty));
Place {
base: base.base,
projection: projection.into_boxed_slice(),
projection: self.tcx.intern_place_elems(&projection),
}
}
......@@ -264,6 +284,10 @@ fn get_discr(&self, body: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
}
impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_local(&mut self,
local: &mut Local,
_: PlaceContext,
......@@ -280,7 +304,7 @@ fn visit_place(
if let PlaceBase::Local(l) = place.base {
// Replace an Local in the remap with a generator struct access
if let Some(&(ty, variant_index, idx)) = self.remap.get(&l) {
replace_base(place, self.make_field(variant_index, idx, ty));
replace_base(place, self.make_field(variant_index, idx, ty), self.tcx);
}
} else {
self.visit_place_base(&mut place.base, context, location);
......@@ -375,7 +399,7 @@ fn make_generator_state_argument_indirect<'tcx>(
body.local_decls.raw[1].ty = ref_gen_ty;
// Add a deref to accesses of the generator state
DerefArgVisitor.visit_body(body);
DerefArgVisitor { tcx }.visit_body(body);
}
fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
......@@ -390,12 +414,13 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
body.local_decls.raw[1].ty = pin_ref_gen_ty;
// Add the Pin field access to accesses of the generator state
PinArgVisitor { ref_gen_ty }.visit_body(body);
PinArgVisitor { ref_gen_ty, tcx }.visit_body(body);
}
fn replace_result_variable<'tcx>(
ret_ty: Ty<'tcx>,
body: &mut Body<'tcx>,
tcx: TyCtxt<'tcx>,
) -> Local {
let source_info = source_info(body);
let new_ret = LocalDecl {
......@@ -416,6 +441,7 @@ fn replace_result_variable<'tcx>(
RenameLocalVisitor {
from: RETURN_PLACE,
to: new_ret_local,
tcx,
}.visit_body(body);
new_ret_local
......@@ -1182,7 +1208,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'
// We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
// RETURN_PLACE then is a fresh unused local with type ret_ty.
let new_ret_local = replace_result_variable(ret_ty, body);
let new_ret_local = replace_result_variable(ret_ty, body, tcx);
// Extract locals which are live across suspension point into `layout`
// `remap` gives a mapping from local indices onto generator struct indices
......
......@@ -461,7 +461,7 @@ fn dest_needs_borrow(place: &Place<'_>) -> bool {
};
caller_body[callsite.bb]
.statements.push(stmt);
tmp.deref()
tmp.deref(self.tcx)
} else {
destination.0
};
......@@ -481,6 +481,7 @@ fn dest_needs_borrow(place: &Place<'_>) -> bool {
return_block,
cleanup_block: cleanup,
in_cleanup_block: false,
tcx: self.tcx,
};
......@@ -562,6 +563,7 @@ fn make_call_args(
let tuple_field = Operand::Move(tuple.clone().field(
Field::new(i),
ty.expect_ty(),
tcx,
));
// Spill to a local to make e.g., `tmp0`.
......@@ -638,6 +640,7 @@ struct Integrator<'a, 'tcx> {
return_block: BasicBlock,
cleanup_block: Option<BasicBlock>,
in_cleanup_block: bool,
tcx: TyCtxt<'tcx>,
}
impl<'a, 'tcx> Integrator<'a, 'tcx> {
......@@ -665,6 +668,10 @@ fn make_integrate_local(&self, local: &Local) -> Local {
}
impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_local(
&mut self,
local: &mut Local,
......
......@@ -29,29 +29,32 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>)
};
// Then carry out those optimizations.
MutVisitor::visit_body(&mut InstCombineVisitor { optimizations }, body);
MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body);
}
}
pub struct InstCombineVisitor<'tcx> {
optimizations: OptimizationList<'tcx>,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
if self.optimizations.and_stars.remove(&location) {
debug!("replacing `&*`: {:?}", rvalue);
let new_place = match rvalue {
Rvalue::Ref(_, _, place) => {
if let &[ref proj_l @ .., proj_r] = place.projection.as_ref() {
let new_projection = proj_l.to_vec().into_boxed_slice();
place.projection = vec![proj_r.clone()].into_boxed_slice();
place.projection = self.tcx().intern_place_elems(&vec![proj_r.clone()]);
Place {
// Replace with dummy
base: mem::replace(&mut place.base, PlaceBase::Local(Local::new(0))),
projection: new_projection,
projection: self.tcx().intern_place_elems(proj_l),
}
} else {
unreachable!();
......
......@@ -228,7 +228,7 @@ fn run_optimization_passes<'tcx>(
) {
run_passes(tcx, body, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[
// Remove all things only needed by analysis
&no_landing_pads::NoLandingPads,
&no_landing_pads::NoLandingPads::new(tcx),
&simplify_branches::SimplifyBranches::new("initial"),
&remove_noop_landing_pads::RemoveNoopLandingPads,
&cleanup_post_borrowck::CleanupNonCodegenStatements,
......@@ -238,7 +238,7 @@ fn run_optimization_passes<'tcx>(
// These next passes must be executed together
&add_call_guards::CriticalCallEdges,
&elaborate_drops::ElaborateDrops,
&no_landing_pads::NoLandingPads,
&no_landing_pads::NoLandingPads::new(tcx),
// AddMovesForPackedDrops needs to run after drop
// elaboration.
&add_moves_for_packed_drops::AddMovesForPackedDrops,
......@@ -257,7 +257,7 @@ fn run_optimization_passes<'tcx>(
// Optimizations begin.
&uniform_array_move_out::RestoreSubsliceArrayMoveOut,
&uniform_array_move_out::RestoreSubsliceArrayMoveOut::new(tcx),
&inline::Inline,
// Lowering generator control-flow and variables
......
......@@ -6,9 +6,17 @@
use rustc::mir::visit::MutVisitor;
use crate::transform::{MirPass, MirSource};
pub struct NoLandingPads;
pub struct NoLandingPads<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> NoLandingPads<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
NoLandingPads { tcx }
}
}
impl<'tcx> MirPass<'tcx> for NoLandingPads {
impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> {
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
no_landing_pads(tcx, body)
}
......@@ -16,11 +24,15 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>)
pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
if tcx.sess.no_landing_pads() {
NoLandingPads.visit_body(body);
NoLandingPads::new(tcx).visit_body(body);
}
}
impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
impl<'tcx> MutVisitor<'tcx> for NoLandingPads<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_terminator_kind(&mut self,
kind: &mut TerminatorKind<'tcx>,
location: Location) {
......
......@@ -17,7 +17,7 @@
use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor};
use rustc::mir::traversal::ReversePostorder;
use rustc::ty::subst::InternalSubsts;
use rustc::ty::TyCtxt;
use rustc::ty::{List, TyCtxt};
use syntax_pos::Span;
use rustc_index::vec::{IndexVec, Idx};
......@@ -321,7 +321,7 @@ fn promote_candidate(
ty,
def_id,
}),
projection: box [],
projection: List::empty(),
}
};
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
......@@ -339,7 +339,7 @@ fn promote_candidate(
&mut place.base,
promoted_place(ty, span).base,
),
projection: box [],
projection: List::empty(),
})
}
_ => bug!()
......@@ -396,6 +396,10 @@ fn promote_candidate(
/// Replaces all temporaries with their promoted counterparts.
impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_local(&mut self,
local: &mut Local,
_: PlaceContext,
......
......@@ -319,7 +319,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'
let map = make_local_map(&mut body.local_decls, locals);
// Update references to all vars and tmps now
LocalUpdater { map }.visit_body(body);
LocalUpdater { map, tcx }.visit_body(body);
body.local_decls.shrink_to_fit();
}
}
......@@ -374,11 +374,16 @@ fn visit_local(&mut self, local: &Local, ctx: PlaceContext, location: Location)
}
}
struct LocalUpdater {
struct LocalUpdater<'tcx> {
map: IndexVec<Local, Option<Local>>,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for LocalUpdater {
impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
// Remove unnecessary StorageLive and StorageDead annotations.
data.statements.retain(|stmt| {
......
......@@ -116,16 +116,13 @@ fn uniform(&mut self,
min_length: size,
from_end: false,
});
self.patch.add_assign(location,
Place::from(temp),
Rvalue::Use(
Operand::Move(
Place {
base: base.clone(),
projection: projection.into_boxed_slice(),
}
)
)
self.patch.add_assign(
location,
Place::from(temp),
Rvalue::Use(Operand::Move(Place {
base: base.clone(),
projection: self.tcx.intern_place_elems(&projection),
})),
);
temp
}).collect();
......@@ -153,16 +150,13 @@ fn uniform(&mut self,
min_length: size,
from_end: false,
});
self.patch.add_assign(location,
dst_place.clone(),
Rvalue::Use(
Operand::Move(
Place {
base: base.clone(),
projection: projection.into_boxed_slice(),
}
)
)
self.patch.add_assign(
location,
dst_place.clone(),
Rvalue::Use(Operand::Move(Place {
base: base.clone(),
projection: self.tcx.intern_place_elems(&projection),
})),
);
}
_ => {}
......@@ -185,9 +179,11 @@ fn uniform(&mut self,
//
// replaced by _10 = move _2[:-1];
pub struct RestoreSubsliceArrayMoveOut;
pub struct RestoreSubsliceArrayMoveOut<'tcx> {
tcx: TyCtxt<'tcx>
}
impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut {
impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> {
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
let mut patch = MirPatch::new(body);
let param_env = tcx.param_env(src.def_id());
......@@ -229,7 +225,9 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx
None
}
});
Self::check_and_patch(*candidate, &items, opt_size, &mut patch, dst_place);
let restore_subslice = RestoreSubsliceArrayMoveOut { tcx };
restore_subslice
.check_and_patch(*candidate, &items, opt_size, &mut patch, dst_place);
}
}
}
......@@ -238,15 +236,20 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx
}
}
impl RestoreSubsliceArrayMoveOut {
impl RestoreSubsliceArrayMoveOut<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
RestoreSubsliceArrayMoveOut { tcx }
}
// Checks that source has size, all locals are inited from same source place and
// indices is an integer interval. If all checks pass do the replacent.
// items are Vec<Option<LocalUse, index in source array, source place for init local>>
fn check_and_patch<'tcx>(candidate: Location,
items: &[Option<(&LocalUse, u32, PlaceRef<'_, 'tcx>)>],
opt_size: Option<u64>,
patch: &mut MirPatch<'tcx>,
dst_place: &Place<'tcx>) {
fn check_and_patch(&self,
candidate: Location,
items: &[Option<(&LocalUse, u32, PlaceRef<'_, 'tcx>)>],
opt_size: Option<u64>,
patch: &mut MirPatch<'tcx>,
dst_place: &Place<'tcx>) {
let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
if opt_size.is_some() && items.iter().all(
......@@ -279,14 +282,14 @@ fn check_and_patch<'tcx>(candidate: Location,
dst_place.clone(),
Rvalue::Use(Operand::Move(Place {
base: src_place.base.clone(),
projection: projection.into_boxed_slice(),
projection: self.tcx.intern_place_elems(&projection),
})),
);
}
}
fn try_get_item_source<'a, 'tcx>(local_use: &LocalUse,
body: &'a Body<'tcx>) -> Option<(u32, PlaceRef<'a, 'tcx>)> {
fn try_get_item_source<'a>(local_use: &LocalUse,
body: &'a Body<'tcx>) -> Option<(u32, PlaceRef<'a, 'tcx>)> {
if let Some(location) = local_use.first_use {
let block = &body[location.block];
if block.statements.len() > location.statement_index {
......
use rustc::mir::*;
use rustc::ty::Ty;
use rustc::ty::{Ty, TyCtxt};
use rustc::ty::layout::VariantIdx;
use rustc_index::vec::Idx;
......@@ -17,6 +17,7 @@ pub fn expand_aggregate<'tcx>(
operands: impl Iterator<Item=(Operand<'tcx>, Ty<'tcx>)> + TrustedLen,
kind: AggregateKind<'tcx>,
source_info: SourceInfo,
tcx: TyCtxt<'tcx>,
) -> impl Iterator<Item=Statement<'tcx>> + TrustedLen {
let mut set_discriminant = None;
let active_field_index = match kind {
......@@ -29,7 +30,7 @@ pub fn expand_aggregate<'tcx>(
},
source_info,
});
lhs = lhs.downcast(adt_def, variant_index);
lhs = lhs.downcast(adt_def, variant_index, tcx);
}
active_field_index
}
......@@ -63,10 +64,10 @@ pub fn expand_aggregate<'tcx>(
// 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)
lhs.clone().field(field, ty, tcx)
};
Statement {
source_info,
......
......@@ -2,6 +2,7 @@
use rustc::mir::{Body, Local, Location, PlaceElem};
use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
use rustc::ty::TyCtxt;
use rustc_index::vec::IndexVec;
use std::mem;
......@@ -47,20 +48,26 @@ pub fn local_info(&self, local: Local) -> &Info {
&self.info[local]
}
fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, new_local: Local) {
fn mutate_defs_and_uses(
&self,
local: Local,
body: &mut Body<'tcx>,
new_local: Local,
tcx: TyCtxt<'tcx>,
) {
for place_use in &self.info[local].defs_and_uses {
MutateUseVisitor::new(local,
new_local,
body).visit_location(body, place_use.location)
MutateUseVisitor::new(local, new_local, body, tcx)
.visit_location(body, place_use.location)
}
}
// FIXME(pcwalton): this should update the def-use chains.
pub fn replace_all_defs_and_uses_with(&self,
local: Local,
body: &mut Body<'_>,
new_local: Local) {
self.mutate_defs_and_uses(local, body, new_local)
body: &mut Body<'tcx>,
new_local: Local,
tcx: TyCtxt<'tcx>) {
self.mutate_defs_and_uses(local, body, new_local, tcx)
}
}
......@@ -114,21 +121,28 @@ pub fn use_count(&self) -> usize {
}
}
struct MutateUseVisitor {
struct MutateUseVisitor<'tcx> {
query: Local,
new_local: Local,
tcx: TyCtxt<'tcx>,
}
impl MutateUseVisitor {
fn new(query: Local, new_local: Local, _: &Body<'_>) -> MutateUseVisitor {
MutateUseVisitor {
query,
new_local,
}
impl MutateUseVisitor<'tcx> {
fn new(
query: Local,
new_local: Local,
_: &Body<'tcx>,
tcx: TyCtxt<'tcx>,
) -> MutateUseVisitor<'tcx> {
MutateUseVisitor { query, new_local, tcx }
}
}
impl MutVisitor<'_> for MutateUseVisitor {
impl MutVisitor<'tcx> for MutateUseVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_local(&mut self,
local: &mut Local,
_context: PlaceContext,
......
......@@ -206,7 +206,7 @@ fn move_paths_for_fields(&self,
self.elaborator.param_env(),
f.ty(self.tcx(), substs),
);
(base_place.clone().field(field, field_ty), subpath)
(base_place.clone().field(field, field_ty, self.tcx()), subpath)
}).collect()
}
......@@ -323,7 +323,7 @@ fn open_drop_for_tuple(&mut self, tys: &[Ty<'tcx>]) -> BasicBlock {
debug!("open_drop_for_tuple({:?}, {:?})", self, tys);
let fields = tys.iter().enumerate().map(|(i, &ty)| {
(self.place.clone().field(Field::new(i), ty),
(self.place.clone().field(Field::new(i), ty, self.tcx()),
self.elaborator.field_subpath(self.path, Field::new(i)))
}).collect();
......@@ -334,7 +334,7 @@ fn open_drop_for_tuple(&mut self, tys: &[Ty<'tcx>]) -> BasicBlock {
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();
let interior = self.place.clone().deref(self.tcx());
let interior_path = self.elaborator.deref_subpath(self.path);
let succ = self.succ; // FIXME(#43234)
......@@ -413,7 +413,7 @@ fn open_drop_for_multivariant(&mut self, adt: &'tcx ty::AdtDef,
if let Some(variant_path) = subpath {
let base_place = self.place.clone().elem(
ProjectionElem::Downcast(Some(adt.variants[variant_index].ident.name),
variant_index));
variant_index), self.tcx());
let fields = self.move_paths_for_fields(
&base_place,
variant_path,
......@@ -586,7 +586,7 @@ fn drop_loop(
BorrowKind::Mut { allow_two_phase_borrow: false },
Place {
base: PlaceBase::Local(cur),
projection: Box::new([ProjectionElem::Deref]),
projection: self.tcx().intern_place_elems(&vec![ProjectionElem::Deref]),
}
),
Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one))
......@@ -594,7 +594,7 @@ fn drop_loop(
(Rvalue::Ref(
tcx.lifetimes.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
self.place.clone().index(cur)),
self.place.clone().index(cur, self.tcx())),
Rvalue::BinaryOp(BinOp::Add, move_(&Place::from(cur)), one))
};
......@@ -627,7 +627,7 @@ fn drop_loop(
let loop_block = self.elaborator.patch().new_block(loop_block);
self.elaborator.patch().patch_terminator(drop_block, TerminatorKind::Drop {
location: ptr.clone().deref(),
location: ptr.clone().deref(tcx),
target: loop_block,
unwind: unwind.into_option()
});
......@@ -653,7 +653,7 @@ fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> Basic
offset: i,
min_length: size,
from_end: false
}),
}, self.tcx()),
self.elaborator.array_subpath(self.path, i, size))
}).collect();
......@@ -901,7 +901,7 @@ fn unelaborated_free_block(
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))
Operand::Move(self.place.clone().field(field, field_ty, self.tcx()))
}).collect();
let call = TerminatorKind::Call {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册