Skip to content

Commit

Permalink
Intern place projection
Browse files Browse the repository at this point in the history
  • Loading branch information
spastorino committed Oct 22, 2019
1 parent a19aed2 commit d32c286
Show file tree
Hide file tree
Showing 31 changed files with 346 additions and 185 deletions.
76 changes: 47 additions & 29 deletions src/librustc/mir/mod.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
)]
Expand Down Expand Up @@ -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),
}
}

Expand Down Expand Up @@ -1939,7 +1946,7 @@ impl From<Local> for Place<'_> {
fn from(local: Local) -> Self {
Place {
base: local.into(),
projection: Box::new([]),
projection: List::empty(),
}
}
}
Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 7 additions & 3 deletions src/librustc/mir/visit.rs
Expand Up @@ -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>,
Expand All @@ -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;
}
Expand All @@ -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),
}
}

Expand Down
25 changes: 23 additions & 2 deletions src/librustc/ty/codec.rs
Expand Up @@ -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`
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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> {
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/ty/context.rs
Expand Up @@ -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>])
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_mir/borrow_check/conflict_errors.rs
Expand Up @@ -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!(
Expand All @@ -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) =
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_mir/borrow_check/nll/renumber.rs
@@ -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};
Expand Down Expand Up @@ -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);

Expand Down
14 changes: 7 additions & 7 deletions src/librustc_mir/build/expr/as_place.rs
Expand Up @@ -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;

Expand All @@ -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),
}
}

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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 {
Expand Down
15 changes: 10 additions & 5 deletions src/librustc_mir/build/expr/as_rvalue.rs
Expand Up @@ -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
)
);
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/expr/into.rs
Expand Up @@ -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()
Expand Down

0 comments on commit d32c286

Please sign in to comment.