Skip to content

Commit ca0e3df

Browse files
authored
Rollup merge of rust-lang#65315 - spastorino:intern-place-projection, r=oli-obk
Intern place projection This should sit on top of rust-lang#65197. After that one merged, I'm gonna rebase on top of it. The important commits are the last three and there's a bunch of code repetition that I'm going to remove but for that I need to refactor some things that probably need to be added before this PR. Anyway this work helps as is because we can run perf tests :). r? @oli-obk /cc @nikomatsakis
2 parents 1c82167 + 5f5903d commit ca0e3df

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1147
-1057
lines changed

src/librustc/mir/mod.rs

+39-58
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
)]
@@ -1824,6 +1825,8 @@ impl<V, T> ProjectionElem<V, T> {
18241825
/// and the index is a local.
18251826
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
18261827

1828+
impl<'tcx> Copy for PlaceElem<'tcx> { }
1829+
18271830
// At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
18281831
#[cfg(target_arch = "x86_64")]
18291832
static_assert_size!(PlaceElem<'_>, 16);
@@ -1846,50 +1849,11 @@ pub struct PlaceRef<'a, 'tcx> {
18461849
}
18471850

18481851
impl<'tcx> Place<'tcx> {
1849-
// FIXME change this back to a const when projection is a shared slice.
1850-
//
1851-
// pub const RETURN_PLACE: Place<'tcx> = Place {
1852-
// base: PlaceBase::Local(RETURN_PLACE),
1853-
// projection: &[],
1854-
// };
1852+
// FIXME change this to a const fn by also making List::empty a const fn.
18551853
pub fn return_place() -> Place<'tcx> {
18561854
Place {
18571855
base: PlaceBase::Local(RETURN_PLACE),
1858-
projection: Box::new([]),
1859-
}
1860-
}
1861-
1862-
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
1863-
self.elem(ProjectionElem::Field(f, ty))
1864-
}
1865-
1866-
pub fn deref(self) -> Place<'tcx> {
1867-
self.elem(ProjectionElem::Deref)
1868-
}
1869-
1870-
pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
1871-
self.elem(ProjectionElem::Downcast(
1872-
Some(adt_def.variants[variant_index].ident.name),
1873-
variant_index,
1874-
))
1875-
}
1876-
1877-
pub fn downcast_unnamed(self, variant_index: VariantIdx) -> Place<'tcx> {
1878-
self.elem(ProjectionElem::Downcast(None, variant_index))
1879-
}
1880-
1881-
pub fn index(self, index: Local) -> Place<'tcx> {
1882-
self.elem(ProjectionElem::Index(index))
1883-
}
1884-
1885-
pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
1886-
// FIXME(spastorino): revisit this again once projection is not a Box<[T]> anymore
1887-
let mut projection = self.projection.into_vec();
1888-
projection.push(elem);
1889-
1890-
Place {
1891-
base: self.base,
1892-
projection: projection.into_boxed_slice(),
1856+
projection: List::empty(),
18931857
}
18941858
}
18951859

@@ -1906,26 +1870,23 @@ impl<'tcx> Place<'tcx> {
19061870
//
19071871
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
19081872
pub fn local_or_deref_local(&self) -> Option<Local> {
1909-
match self {
1910-
Place {
1911-
base: PlaceBase::Local(local),
1912-
projection: box [],
1873+
match self.as_ref() {
1874+
PlaceRef {
1875+
base: &PlaceBase::Local(local),
1876+
projection: &[],
19131877
} |
1914-
Place {
1915-
base: PlaceBase::Local(local),
1916-
projection: box [ProjectionElem::Deref],
1917-
} => Some(*local),
1878+
PlaceRef {
1879+
base: &PlaceBase::Local(local),
1880+
projection: &[ProjectionElem::Deref],
1881+
} => Some(local),
19181882
_ => None,
19191883
}
19201884
}
19211885

19221886
/// If this place represents a local variable like `_X` with no
19231887
/// projections, return `Some(_X)`.
19241888
pub fn as_local(&self) -> Option<Local> {
1925-
match self {
1926-
Place { projection: box [], base: PlaceBase::Local(l) } => Some(*l),
1927-
_ => None,
1928-
}
1889+
self.as_ref().as_local()
19291890
}
19301891

19311892
pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
@@ -1940,7 +1901,7 @@ impl From<Local> for Place<'_> {
19401901
fn from(local: Local) -> Self {
19411902
Place {
19421903
base: local.into(),
1943-
projection: Box::new([]),
1904+
projection: List::empty(),
19441905
}
19451906
}
19461907
}
@@ -1969,6 +1930,15 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
19691930
_ => None,
19701931
}
19711932
}
1933+
1934+
/// If this place represents a local variable like `_X` with no
1935+
/// projections, return `Some(_X)`.
1936+
pub fn as_local(&self) -> Option<Local> {
1937+
match self {
1938+
PlaceRef { base: PlaceBase::Local(l), projection: [] } => Some(*l),
1939+
_ => None,
1940+
}
1941+
}
19721942
}
19731943

19741944
impl Debug for Place<'_> {
@@ -3182,6 +3152,17 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> {
31823152
}
31833153
}
31843154

3155+
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
3156+
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
3157+
let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
3158+
folder.tcx().intern_place_elems(&v)
3159+
}
3160+
3161+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
3162+
self.iter().any(|t| t.visit_with(visitor))
3163+
}
3164+
}
3165+
31853166
impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> {
31863167
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
31873168
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

+68-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// ignore-tidy-filelength
12
//! Type context book-keeping.
23
34
use crate::arena::Arena;
@@ -21,7 +22,7 @@ use crate::middle::cstore::EncodedMetadata;
2122
use crate::middle::lang_items;
2223
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
2324
use crate::middle::stability;
24-
use crate::mir::{Body, interpret, ProjectionKind, Promoted};
25+
use crate::mir::{Body, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
2526
use crate::mir::interpret::{ConstValue, Allocation, Scalar};
2627
use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst};
2728
use crate::ty::ReprOptions;
@@ -106,6 +107,7 @@ pub struct CtxtInterners<'tcx> {
106107
goal: InternedSet<'tcx, GoalKind<'tcx>>,
107108
goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
108109
projs: InternedSet<'tcx, List<ProjectionKind>>,
110+
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
109111
const_: InternedSet<'tcx, Const<'tcx>>,
110112
}
111113

@@ -124,6 +126,7 @@ impl<'tcx> CtxtInterners<'tcx> {
124126
goal: Default::default(),
125127
goal_list: Default::default(),
126128
projs: Default::default(),
129+
place_elems: Default::default(),
127130
const_: Default::default(),
128131
}
129132
}
@@ -2142,6 +2145,13 @@ impl<'tcx> Borrow<[ProjectionKind]>
21422145
}
21432146
}
21442147

2148+
impl<'tcx> Borrow<[PlaceElem<'tcx>]>
2149+
for Interned<'tcx, List<PlaceElem<'tcx>>> {
2150+
fn borrow(&self) -> &[PlaceElem<'tcx>] {
2151+
&self.0[..]
2152+
}
2153+
}
2154+
21452155
impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
21462156
fn borrow(&self) -> &RegionKind {
21472157
&self.0
@@ -2242,7 +2252,8 @@ slice_interners!(
22422252
predicates: _intern_predicates(Predicate<'tcx>),
22432253
clauses: _intern_clauses(Clause<'tcx>),
22442254
goal_list: _intern_goals(Goal<'tcx>),
2245-
projs: _intern_projs(ProjectionKind)
2255+
projs: _intern_projs(ProjectionKind),
2256+
place_elems: _intern_place_elems(PlaceElem<'tcx>)
22462257
);
22472258

22482259
impl<'tcx> TyCtxt<'tcx> {
@@ -2584,6 +2595,48 @@ impl<'tcx> TyCtxt<'tcx> {
25842595
self.mk_ty(Opaque(def_id, substs))
25852596
}
25862597

2598+
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
2599+
self.mk_place_elem(place, PlaceElem::Field(f, ty))
2600+
}
2601+
2602+
pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
2603+
self.mk_place_elem(place, PlaceElem::Deref)
2604+
}
2605+
2606+
pub fn mk_place_downcast(
2607+
self,
2608+
place: Place<'tcx>,
2609+
adt_def: &'tcx AdtDef,
2610+
variant_index: VariantIdx,
2611+
) -> Place<'tcx> {
2612+
self.mk_place_elem(
2613+
place,
2614+
PlaceElem::Downcast(Some(adt_def.variants[variant_index].ident.name), variant_index),
2615+
)
2616+
}
2617+
2618+
pub fn mk_place_downcast_unnamed(
2619+
self,
2620+
place: Place<'tcx>,
2621+
variant_index: VariantIdx,
2622+
) -> Place<'tcx> {
2623+
self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
2624+
}
2625+
2626+
pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
2627+
self.mk_place_elem(place, PlaceElem::Index(index))
2628+
}
2629+
2630+
/// This method copies `Place`'s projection, add an element and reintern it. Should not be used
2631+
/// to build a full `Place` it's just a convenient way to grab a projection and modify it in
2632+
/// flight.
2633+
pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
2634+
let mut projection = place.projection.to_vec();
2635+
projection.push(elem);
2636+
2637+
Place { base: place.base, projection: self.intern_place_elems(&projection) }
2638+
}
2639+
25872640
pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
25882641
-> &'tcx List<ExistentialPredicate<'tcx>> {
25892642
assert!(!eps.is_empty());
@@ -2628,6 +2681,14 @@ impl<'tcx> TyCtxt<'tcx> {
26282681
}
26292682
}
26302683

2684+
pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
2685+
if ts.len() == 0 {
2686+
List::empty()
2687+
} else {
2688+
self._intern_place_elems(ts)
2689+
}
2690+
}
2691+
26312692
pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVarInfos<'tcx> {
26322693
if ts.len() == 0 {
26332694
List::empty()
@@ -2690,6 +2751,11 @@ impl<'tcx> TyCtxt<'tcx> {
26902751
iter.intern_with(|xs| self.intern_substs(xs))
26912752
}
26922753

2754+
pub fn mk_place_elems<I: InternAs<[PlaceElem<'tcx>],
2755+
&'tcx List<PlaceElem<'tcx>>>>(self, iter: I) -> I::Output {
2756+
iter.intern_with(|xs| self.intern_place_elems(xs))
2757+
}
2758+
26932759
pub fn mk_substs_trait(self,
26942760
self_ty: Ty<'tcx>,
26952761
rest: &[GenericArg<'tcx>])

0 commit comments

Comments
 (0)