Skip to content

Commit d32c286

Browse files
committed
Intern place projection
1 parent a19aed2 commit d32c286

31 files changed

+346
-185
lines changed

src/librustc/mir/mod.rs

+47-29
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ use crate::ty::layout::VariantIdx;
1515
use crate::ty::print::{FmtPrinter, Printer};
1616
use crate::ty::subst::{Subst, SubstsRef};
1717
use crate::ty::{
18-
self, AdtDef, CanonicalUserTypeAnnotations, Region, Ty, TyCtxt,
19-
UserTypeAnnotationIndex,
18+
self, AdtDef, CanonicalUserTypeAnnotations, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex,
2019
};
2120

2221
use polonius_engine::Atom;
@@ -1712,15 +1711,17 @@ impl Debug for Statement<'_> {
17121711
/// A path to a value; something that can be evaluated without
17131712
/// changing or disturbing program state.
17141713
#[derive(
1715-
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
1714+
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable,
17161715
)]
17171716
pub struct Place<'tcx> {
17181717
pub base: PlaceBase<'tcx>,
17191718

17201719
/// projection out of a place (access a field, deref a pointer, etc)
1721-
pub projection: Box<[PlaceElem<'tcx>]>,
1720+
pub projection: &'tcx List<PlaceElem<'tcx>>,
17221721
}
17231722

1723+
impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {}
1724+
17241725
#[derive(
17251726
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
17261727
)]
@@ -1848,50 +1849,56 @@ pub struct PlaceRef<'a, 'tcx> {
18481849
}
18491850

18501851
impl<'tcx> Place<'tcx> {
1851-
// FIXME change this back to a const when projection is a shared slice.
1852-
//
1853-
// pub const RETURN_PLACE: Place<'tcx> = Place {
1854-
// base: PlaceBase::Local(RETURN_PLACE),
1855-
// projection: &[],
1856-
// };
1852+
// FIXME change this to a const fn by also making List::empty a const fn.
18571853
pub fn return_place() -> Place<'tcx> {
18581854
Place {
18591855
base: PlaceBase::Local(RETURN_PLACE),
1860-
projection: Box::new([]),
1856+
projection: List::empty(),
18611857
}
18621858
}
18631859

1864-
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
1865-
self.elem(ProjectionElem::Field(f, ty))
1860+
pub fn field(self, f: Field, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
1861+
self.elem(ProjectionElem::Field(f, ty), tcx)
18661862
}
18671863

1868-
pub fn deref(self) -> Place<'tcx> {
1869-
self.elem(ProjectionElem::Deref)
1864+
pub fn deref(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
1865+
self.elem(ProjectionElem::Deref, tcx)
18701866
}
18711867

1872-
pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
1873-
self.elem(ProjectionElem::Downcast(
1874-
Some(adt_def.variants[variant_index].ident.name),
1875-
variant_index,
1876-
))
1868+
pub fn downcast(
1869+
self,
1870+
adt_def: &'tcx AdtDef,
1871+
variant_index: VariantIdx,
1872+
tcx: TyCtxt<'tcx>,
1873+
) -> Place<'tcx> {
1874+
self.elem(
1875+
ProjectionElem::Downcast(
1876+
Some(adt_def.variants[variant_index].ident.name),
1877+
variant_index,
1878+
),
1879+
tcx,
1880+
)
18771881
}
18781882

1879-
pub fn downcast_unnamed(self, variant_index: VariantIdx) -> Place<'tcx> {
1880-
self.elem(ProjectionElem::Downcast(None, variant_index))
1883+
pub fn downcast_unnamed(self, variant_index: VariantIdx, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
1884+
self.elem(ProjectionElem::Downcast(None, variant_index), tcx)
18811885
}
18821886

1883-
pub fn index(self, index: Local) -> Place<'tcx> {
1884-
self.elem(ProjectionElem::Index(index))
1887+
pub fn index(self, index: Local, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
1888+
self.elem(ProjectionElem::Index(index), tcx)
18851889
}
18861890

1887-
pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
1888-
// FIXME(spastorino): revisit this again once projection is not a Box<[T]> anymore
1889-
let mut projection = self.projection.into_vec();
1891+
/// This method copies `Place`'s projection, add an element and reintern it. Should not be used
1892+
/// to build a full `Place` it's just a convenient way to grab a projection and modify it in
1893+
/// flight.
1894+
// FIXME: It may be a better idea to move all these methods to `PlaceBuilder`
1895+
pub fn elem(self, elem: PlaceElem<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
1896+
let mut projection = self.projection.to_vec();
18901897
projection.push(elem);
18911898

18921899
Place {
18931900
base: self.base,
1894-
projection: projection.into_boxed_slice(),
1901+
projection: tcx.intern_place_elems(&projection),
18951902
}
18961903
}
18971904

@@ -1939,7 +1946,7 @@ impl From<Local> for Place<'_> {
19391946
fn from(local: Local) -> Self {
19401947
Place {
19411948
base: local.into(),
1942-
projection: Box::new([]),
1949+
projection: List::empty(),
19431950
}
19441951
}
19451952
}
@@ -3190,6 +3197,17 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> {
31903197
}
31913198
}
31923199

3200+
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
3201+
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
3202+
let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
3203+
folder.tcx().intern_place_elems(&v)
3204+
}
3205+
3206+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
3207+
self.iter().any(|t| t.visit_with(visitor))
3208+
}
3209+
}
3210+
31933211
impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> {
31943212
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
31953213
Static {

src/librustc/mir/visit.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,8 @@ macro_rules! make_mir_visitor {
784784

785785
macro_rules! visit_place_fns {
786786
(mut) => (
787+
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
788+
787789
fn super_place(
788790
&mut self,
789791
place: &mut Place<'tcx>,
@@ -793,19 +795,21 @@ macro_rules! visit_place_fns {
793795
self.visit_place_base(&mut place.base, context, location);
794796

795797
if let Some(new_projection) = self.process_projection(&place.projection) {
796-
place.projection = new_projection;
798+
place.projection = self.tcx().intern_place_elems(&new_projection);
797799
}
798800
}
799801

800802
fn process_projection(
801803
&mut self,
802804
projection: &'a [PlaceElem<'tcx>],
803-
) -> Option<Box<[PlaceElem<'tcx>]>> {
805+
) -> Option<Vec<PlaceElem<'tcx>>> {
804806
let mut projection = Cow::Borrowed(projection);
805807

806808
for i in 0..projection.len() {
807809
if let Some(elem) = projection.get(i) {
808810
if let Some(elem) = self.process_projection_elem(elem) {
811+
// This converts the borrowed projection into `Cow::Owned(_)` and returns a
812+
// clone of the projection so we can mutate and reintern later.
809813
let vec = projection.to_mut();
810814
vec[i] = elem;
811815
}
@@ -814,7 +818,7 @@ macro_rules! visit_place_fns {
814818

815819
match projection {
816820
Cow::Borrowed(_) => None,
817-
Cow::Owned(vec) => Some(vec.into_boxed_slice()),
821+
Cow::Owned(vec) => Some(vec),
818822
}
819823
}
820824

src/librustc/ty/codec.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ use rustc_data_structures::fx::FxHashMap;
1313
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
1414
use std::hash::Hash;
1515
use std::intrinsics;
16-
use crate::ty::{self, Ty, TyCtxt};
16+
use crate::ty::{self, List, Ty, TyCtxt};
1717
use crate::ty::subst::SubstsRef;
18-
use crate::mir::interpret::Allocation;
18+
use crate::mir::{self, interpret::Allocation};
1919
use syntax_pos::Span;
2020

2121
/// The shorthand encoding uses an enum's variant index `usize`
@@ -218,6 +218,18 @@ where
218218
Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
219219
}
220220

221+
#[inline]
222+
pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error>
223+
where
224+
D: TyDecoder<'tcx>,
225+
{
226+
let base: mir::PlaceBase<'tcx> = Decodable::decode(decoder)?;
227+
let len = decoder.read_usize()?;
228+
let projection: &'tcx List<mir::PlaceElem<'tcx>> =
229+
decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
230+
Ok(mir::Place { base, projection })
231+
}
232+
221233
#[inline]
222234
pub fn decode_region<D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
223235
where
@@ -413,6 +425,15 @@ macro_rules! implement_ty_decoder {
413425
}
414426
}
415427

428+
impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>>
429+
for $DecoderName<$($typaram),*> {
430+
fn specialized_decode(
431+
&mut self
432+
) -> Result<$crate::mir::Place<'tcx>, Self::Error> {
433+
decode_place(self)
434+
}
435+
}
436+
416437
impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
417438
for $DecoderName<$($typaram),*> {
418439
fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {

src/librustc/ty/context.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2711,6 +2711,11 @@ impl<'tcx> TyCtxt<'tcx> {
27112711
iter.intern_with(|xs| self.intern_substs(xs))
27122712
}
27132713

2714+
pub fn mk_place_elems<I: InternAs<[PlaceElem<'tcx>],
2715+
&'tcx List<PlaceElem<'tcx>>>>(self, iter: I) -> I::Output {
2716+
iter.intern_with(|xs| self.intern_place_elems(xs))
2717+
}
2718+
27142719
pub fn mk_substs_trait(self,
27152720
self_ty: Ty<'tcx>,
27162721
rest: &[GenericArg<'tcx>])

src/librustc_mir/borrow_check/conflict_errors.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -707,10 +707,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
707707
_ => drop_span,
708708
};
709709

710+
let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection);
711+
710712
if self.access_place_error_reported
711713
.contains(&(Place {
712714
base: root_place.base.clone(),
713-
projection: root_place.projection.to_vec().into_boxed_slice(),
715+
projection: root_place_projection,
714716
}, borrow_span))
715717
{
716718
debug!(
@@ -723,7 +725,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
723725
self.access_place_error_reported
724726
.insert((Place {
725727
base: root_place.base.clone(),
726-
projection: root_place.projection.to_vec().into_boxed_slice(),
728+
projection: root_place_projection,
727729
}, borrow_span));
728730

729731
if let StorageDeadOrDrop::Destructor(dropped_ty) =

src/librustc_mir/borrow_check/nll/renumber.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc::ty::subst::SubstsRef;
2-
use rustc::ty::{self, Ty, TypeFoldable};
2+
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
33
use rustc::mir::{Body, Location, PlaceElem, Promoted};
44
use rustc::mir::visit::{MutVisitor, TyContext};
55
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
@@ -54,6 +54,10 @@ impl<'a, 'tcx> NLLVisitor<'a, 'tcx> {
5454
}
5555

5656
impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> {
57+
fn tcx(&self) -> TyCtxt<'tcx> {
58+
self.infcx.tcx
59+
}
60+
5761
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
5862
debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context);
5963

src/librustc_mir/build/expr/as_place.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder};
66
use crate::hair::*;
77
use rustc::mir::interpret::{PanicInfo::BoundsCheck};
88
use rustc::mir::*;
9-
use rustc::ty::{CanonicalUserTypeAnnotation, Ty, Variance};
9+
use rustc::ty::{CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance};
1010

1111
use rustc_index::vec::Idx;
1212

@@ -23,10 +23,10 @@ struct PlaceBuilder<'tcx> {
2323
}
2424

2525
impl PlaceBuilder<'tcx> {
26-
fn into_place(self) -> Place<'tcx> {
26+
fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
2727
Place {
2828
base: self.base,
29-
projection: self.projection.into_boxed_slice(),
29+
projection: tcx.intern_place_elems(&self.projection),
3030
}
3131
}
3232

@@ -73,7 +73,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7373
M: Mirror<'tcx, Output = Expr<'tcx>>,
7474
{
7575
let place_builder = unpack!(block = self.as_place_builder(block, expr));
76-
block.and(place_builder.into_place())
76+
block.and(place_builder.into_place(self.hir.tcx()))
7777
}
7878

7979
/// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -96,7 +96,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9696
M: Mirror<'tcx, Output = Expr<'tcx>>,
9797
{
9898
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
99-
block.and(place_builder.into_place())
99+
block.and(place_builder.into_place(self.hir.tcx()))
100100
}
101101

102102
/// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -165,7 +165,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
165165
Mutability::Not,
166166
));
167167

168-
let slice = place_builder.clone().into_place();
168+
let slice = place_builder.clone().into_place(this.hir.tcx());
169169
// bounds check:
170170
let (len, lt) = (
171171
this.temp(usize_ty.clone(), expr_span),
@@ -225,7 +225,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
225225
}
226226
);
227227

228-
let place = place_builder.clone().into_place();
228+
let place = place_builder.clone().into_place(this.hir.tcx());
229229
this.cfg.push(
230230
block,
231231
Statement {

src/librustc_mir/build/expr/as_rvalue.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
139139
// initialize the box contents:
140140
unpack!(
141141
block = this.into(
142-
&Place::from(result).deref(),
142+
&Place::from(result).deref(this.hir.tcx()),
143143
block, value
144144
)
145145
);
@@ -296,8 +296,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
296296
.zip(field_types.into_iter())
297297
.map(|(n, ty)| match fields_map.get(&n) {
298298
Some(v) => v.clone(),
299-
None => this.consume_by_copy_or_move(base.clone().field(n, ty)),
300-
}).collect()
299+
None => this.consume_by_copy_or_move(base.clone().field(
300+
n,
301+
ty,
302+
this.hir.tcx(),
303+
)),
304+
})
305+
.collect()
301306
} else {
302307
field_names
303308
.iter()
@@ -397,8 +402,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
397402
let val_fld = Field::new(0);
398403
let of_fld = Field::new(1);
399404

400-
let val = result_value.clone().field(val_fld, ty);
401-
let of = result_value.field(of_fld, bool_ty);
405+
let val = result_value.clone().field(val_fld, ty, self.hir.tcx());
406+
let of = result_value.field(of_fld, bool_ty, self.hir.tcx());
402407

403408
let err = PanicInfo::Overflow(op);
404409

src/librustc_mir/build/expr/into.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
235235
});
236236
let ptr_temp = Place::from(ptr_temp);
237237
let block = unpack!(this.into(&ptr_temp, block, ptr));
238-
this.into(&ptr_temp.deref(), block, val)
238+
this.into(&ptr_temp.deref(this.hir.tcx()), block, val)
239239
} else {
240240
let args: Vec<_> = args
241241
.into_iter()

0 commit comments

Comments
 (0)