Intern place projection

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