Intern place projection
This commit is contained in:
parent
a19aed2226
commit
d32c2865d6
31 changed files with 346 additions and 185 deletions
|
|
@ -15,8 +15,7 @@ use crate::ty::layout::VariantIdx;
|
|||
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 @@ impl Debug for Statement<'_> {
|
|||
/// 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 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ macro_rules! make_mir_visitor {
|
|||
|
||||
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 @@ macro_rules! visit_place_fns {
|
|||
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 @@ macro_rules! visit_place_fns {
|
|||
|
||||
match projection {
|
||||
Cow::Borrowed(_) => None,
|
||||
Cow::Owned(vec) => Some(vec.into_boxed_slice()),
|
||||
Cow::Owned(vec) => Some(vec),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ use rustc_data_structures::fx::FxHashMap;
|
|||
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 @@ where
|
|||
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 @@ macro_rules! implement_ty_decoder {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'tcx> TyCtxt<'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 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
_ => 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 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
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) =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
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 @@ impl<'a, 'tcx> 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) {
|
||||
debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
|||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
);
|
||||
|
||||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// 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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
.zip(field_types.into_iter())
|
||||
.map(|(n, ty)| match fields_map.get(&n) {
|
||||
Some(v) => v.clone(),
|
||||
None => this.consume_by_copy_or_move(base.clone().field(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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let val_fld = Field::new(0);
|
||||
let of_fld = Field::new(1);
|
||||
|
||||
let val = result_value.clone().field(val_fld, ty);
|
||||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
});
|
||||
let ptr_temp = Place::from(ptr_temp);
|
||||
let block = unpack!(this.into(&ptr_temp, block, ptr));
|
||||
this.into(&ptr_temp.deref(), block, val)
|
||||
this.into(&ptr_temp.deref(this.hir.tcx()), block, val)
|
||||
} else {
|
||||
let args: Vec<_> = args
|
||||
.into_iter()
|
||||
|
|
|
|||
|
|
@ -948,7 +948,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
});
|
||||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// `(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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
|||
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 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
|||
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 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
|||
// Box starts out uninitialized - need to create a separate
|
||||
// move-path for the interior so it will be separate from
|
||||
// the exterior.
|
||||
self.create_move_path(&place.clone().deref());
|
||||
self.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 @@ impl CloneShimBuilder<'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 @@ impl CloneShimBuilder<'tcx> {
|
|||
// BB #2
|
||||
// `dest[i] = Clone::clone(src[beg])`;
|
||||
// Goto #3 if ok, #5 if unwinding happens.
|
||||
let dest_field = dest.clone().index(beg);
|
||||
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 @@ impl CloneShimBuilder<'tcx> {
|
|||
// 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 @@ impl CloneShimBuilder<'tcx> {
|
|||
let mut previous_field = None;
|
||||
for (i, ity) in tys.enumerate() {
|
||||
let field = Field::new(i);
|
||||
let src_field = src.clone().field(field, ity);
|
||||
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 @@ use crate::transform::{MirPass, MirSource};
|
|||
|
||||
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 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
|
|||
}
|
||||
|
||||
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 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'tcx> Action<'tcx> {
|
|||
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 @@ impl<'tcx> Action<'tcx> {
|
|||
}
|
||||
|
||||
// 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 @@ impl<'tcx> Action<'tcx> {
|
|||
|
||||
// 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 @@ impl<'tcx> Action<'tcx> {
|
|||
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 @@ impl<'tcx> MirPass<'tcx> for Deaggregator {
|
|||
}),
|
||||
*kind,
|
||||
source_info,
|
||||
tcx,
|
||||
))
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ impl 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) {
|
||||
*ty = self.tcx.erase_regions(ty);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,12 +74,17 @@ use crate::util::liveness;
|
|||
|
||||
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 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
|
|||
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 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
|
|||
|
||||
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 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
|
|||
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 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ impl TransformVisitor<'tcx> {
|
|||
// Create a Place referencing a generator struct field
|
||||
fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
|
||||
let self_place = Place::from(self_arg());
|
||||
let base = self_place.downcast_unnamed(variant_index);
|
||||
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 @@ impl TransformVisitor<'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 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
|
|||
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 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
|||
|
||||
// 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 @@ impl Inliner<'tcx> {
|
|||
};
|
||||
caller_body[callsite.bb]
|
||||
.statements.push(stmt);
|
||||
tmp.deref()
|
||||
tmp.deref(self.tcx)
|
||||
} else {
|
||||
destination.0
|
||||
};
|
||||
|
|
@ -481,6 +481,7 @@ impl Inliner<'tcx> {
|
|||
return_block,
|
||||
cleanup_block: cleanup,
|
||||
in_cleanup_block: false,
|
||||
tcx: self.tcx,
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -562,6 +563,7 @@ impl Inliner<'tcx> {
|
|||
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 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
|
|||
}
|
||||
|
||||
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 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
|
|||
};
|
||||
|
||||
// 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::*;
|
|||
use rustc::mir::visit::MutVisitor;
|
||||
use crate::transform::{MirPass, MirSource};
|
||||
|
||||
pub struct NoLandingPads;
|
||||
pub struct NoLandingPads<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for NoLandingPads {
|
||||
impl<'tcx> NoLandingPads<'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||
NoLandingPads { tcx }
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'tcx> MirPass<'tcx> for NoLandingPads {
|
|||
|
||||
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::*;
|
|||
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 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
ty,
|
||||
def_id,
|
||||
}),
|
||||
projection: box [],
|
||||
projection: List::empty(),
|
||||
}
|
||||
};
|
||||
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
||||
|
|
@ -339,7 +339,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
&mut place.base,
|
||||
promoted_place(ty, span).base,
|
||||
),
|
||||
projection: box [],
|
||||
projection: List::empty(),
|
||||
})
|
||||
}
|
||||
_ => bug!()
|
||||
|
|
@ -396,6 +396,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
|
||||
/// 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 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals {
|
|||
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
|
|||
//
|
||||
// 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 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut {
|
|||
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 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ impl RestoreSubsliceArrayMoveOut {
|
|||
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 {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
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 @@ impl DefUseAnalysis {
|
|||
&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 @@ impl Info {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ where
|
|||
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 @@ where
|
|||
debug!("open_drop_for_tuple({:?}, {:?})", self, tys);
|
||||
|
||||
let fields = tys.iter().enumerate().map(|(i, &ty)| {
|
||||
(self.place.clone().field(Field::new(i), ty),
|
||||
(self.place.clone().field(Field::new(i), ty, self.tcx()),
|
||||
self.elaborator.field_subpath(self.path, Field::new(i)))
|
||||
}).collect();
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ where
|
|||
fn open_drop_for_box(&mut self, adt: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>) -> BasicBlock {
|
||||
debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs);
|
||||
|
||||
let interior = self.place.clone().deref();
|
||||
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 @@ where
|
|||
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 @@ where
|
|||
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 @@ where
|
|||
(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 @@ where
|
|||
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 @@ where
|
|||
offset: i,
|
||||
min_length: size,
|
||||
from_end: false
|
||||
}),
|
||||
}, self.tcx()),
|
||||
self.elaborator.array_subpath(self.path, i, size))
|
||||
}).collect();
|
||||
|
||||
|
|
@ -901,7 +901,7 @@ where
|
|||
let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
|
||||
let field = Field::new(i);
|
||||
let field_ty = f.ty(self.tcx(), substs);
|
||||
Operand::Move(self.place.clone().field(field, field_ty))
|
||||
Operand::Move(self.place.clone().field(field, field_ty, self.tcx()))
|
||||
}).collect();
|
||||
|
||||
let call = TerminatorKind::Call {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue