Skip to content

Commit 4bb7c02

Browse files
committed
add CompoundPlace and CompoundPlaceRef
1 parent 4793ef5 commit 4bb7c02

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,30 @@ impl Debug for PlaceRef<'_> {
12701270
}
12711271
}
12721272

1273+
impl Debug for CompoundPlace<'_> {
1274+
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1275+
self.as_ref().fmt(fmt)
1276+
}
1277+
}
1278+
1279+
impl Debug for CompoundPlaceRef<'_> {
1280+
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1281+
pre_fmt_projection(self.last_projection, fmt)?;
1282+
for projection in self.projection_chain_base.iter().rev() {
1283+
pre_fmt_projection(projection, fmt)?;
1284+
}
1285+
1286+
write!(fmt, "{:?}", self.local)?;
1287+
1288+
for projection in self.projection_chain_base {
1289+
post_fmt_projection(projection, fmt)?;
1290+
}
1291+
post_fmt_projection(self.last_projection, fmt)?;
1292+
1293+
Ok(())
1294+
}
1295+
}
1296+
12731297
fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> fmt::Result {
12741298
for &elem in projection.iter().rev() {
12751299
match elem {

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@ impl<'tcx> PlaceTy<'tcx> {
157157
elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem))
158158
}
159159

160+
pub fn projection_chain_ty(
161+
self,
162+
tcx: TyCtxt<'tcx>,
163+
chain: &[&List<PlaceElem<'tcx>>],
164+
) -> PlaceTy<'tcx> {
165+
chain
166+
.iter()
167+
.flat_map(|&elems| elems)
168+
.fold(self, |place_ty, elem| place_ty.projection_ty(tcx, elem))
169+
}
170+
160171
/// Convenience wrapper around `projection_ty_core` for `PlaceElem`,
161172
/// where we can just use the `Ty` that is already stored inline on
162173
/// field projection elems.
@@ -544,6 +555,88 @@ impl From<Local> for PlaceRef<'_> {
544555
}
545556
}
546557

558+
/// A place possibly containing derefs in the middle of its projection by chaining projection lists.
559+
///
560+
/// In `AnalysisPhase::PostCleanup` and later, [`Place`] and [`PlaceRef`] cannot represent these
561+
/// kinds of places.
562+
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable, TypeFoldable, TypeVisitable)]
563+
pub struct CompoundPlace<'tcx> {
564+
pub local: Local,
565+
/// Invariants:
566+
/// - All segments in the chain other than the first must start with a deref.
567+
/// - Derefs may only appear at the start of a segment.
568+
/// - No segment may be empty.
569+
pub projection_chain: &'tcx List<&'tcx List<PlaceElem<'tcx>>>,
570+
}
571+
572+
/// Borrowed form of [`CompoundPlace`].
573+
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
574+
pub struct CompoundPlaceRef<'tcx> {
575+
pub local: Local,
576+
pub projection_chain_base: &'tcx [&'tcx List<PlaceElem<'tcx>>],
577+
pub last_projection: &'tcx [PlaceElem<'tcx>],
578+
}
579+
580+
// these impls are bare-bones for now
581+
impl<'tcx> CompoundPlace<'tcx> {
582+
pub fn as_ref(&self) -> CompoundPlaceRef<'tcx> {
583+
let (last, base) = self
584+
.projection_chain
585+
.split_last()
586+
.map(|(&last, base)| (last, base))
587+
.unwrap_or_default();
588+
589+
CompoundPlaceRef { local: self.local, projection_chain_base: base, last_projection: last }
590+
}
591+
592+
pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
593+
where
594+
D: HasLocalDecls<'tcx>,
595+
{
596+
PlaceTy::from_ty(local_decls.local_decls()[self.local].ty)
597+
.projection_chain_ty(tcx, self.projection_chain)
598+
}
599+
600+
pub fn iter_projections(
601+
self,
602+
) -> impl Iterator<Item = (CompoundPlaceRef<'tcx>, PlaceElem<'tcx>)> + DoubleEndedIterator {
603+
self.projection_chain.iter().enumerate().flat_map(move |(i, projs)| {
604+
projs.iter().enumerate().map(move |(j, elem)| {
605+
let base = if j == 0 && i > 0 {
606+
// last_projection should only be empty if projection_chain_base is too
607+
// otherwise it has to have a deref at least
608+
609+
debug_assert_eq!(elem, PlaceElem::Deref);
610+
CompoundPlaceRef {
611+
local: self.local,
612+
projection_chain_base: &self.projection_chain[..i - 1],
613+
last_projection: &projs[..=j],
614+
}
615+
} else {
616+
CompoundPlaceRef {
617+
local: self.local,
618+
projection_chain_base: &self.projection_chain[..i],
619+
last_projection: &projs[..j],
620+
}
621+
};
622+
623+
(base, elem)
624+
})
625+
})
626+
}
627+
}
628+
629+
impl<'tcx> CompoundPlaceRef<'tcx> {
630+
pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
631+
where
632+
D: HasLocalDecls<'tcx>,
633+
{
634+
PlaceTy::from_ty(local_decls.local_decls()[self.local].ty)
635+
.projection_chain_ty(tcx, self.projection_chain_base)
636+
.multi_projection_ty(tcx, self.last_projection)
637+
}
638+
}
639+
547640
///////////////////////////////////////////////////////////////////////////
548641
// Operands
549642

compiler/rustc_middle/src/ty/context.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ pub struct CtxtInterners<'tcx> {
934934
clauses: InternedSet<'tcx, ListWithCachedTypeInfo<Clause<'tcx>>>,
935935
projs: InternedSet<'tcx, List<ProjectionKind>>,
936936
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
937+
place_elem_chains: InternedSet<'tcx, List<&'tcx List<PlaceElem<'tcx>>>>,
937938
const_: InternedSet<'tcx, WithCachedTypeInfo<ty::ConstKind<'tcx>>>,
938939
pat: InternedSet<'tcx, PatternKind<'tcx>>,
939940
const_allocation: InternedSet<'tcx, Allocation>,
@@ -972,6 +973,7 @@ impl<'tcx> CtxtInterners<'tcx> {
972973
clauses: InternedSet::with_capacity(N),
973974
projs: InternedSet::with_capacity(N * 4),
974975
place_elems: InternedSet::with_capacity(N * 2),
976+
place_elem_chains: InternedSet::with_capacity(N * 2), // FIXME non-emperical factor - just copying place_elems
975977
const_: InternedSet::with_capacity(N * 2),
976978
pat: InternedSet::with_capacity(N),
977979
const_allocation: InternedSet::with_capacity(N),
@@ -2779,6 +2781,7 @@ slice_interners!(
27792781
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
27802782
projs: pub mk_projs(ProjectionKind),
27812783
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
2784+
place_elem_chains: pub mk_place_elem_chain(&'tcx List<PlaceElem<'tcx>>),
27822785
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
27832786
fields: pub mk_fields(FieldIdx),
27842787
local_def_ids: intern_local_def_ids(LocalDefId),
@@ -3169,6 +3172,14 @@ impl<'tcx> TyCtxt<'tcx> {
31693172
T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
31703173
}
31713174

3175+
pub fn mk_place_elem_chain_from_iter<I, T>(self, iter: I) -> T::Output
3176+
where
3177+
I: Iterator<Item = T>,
3178+
T: CollectAndApply<&'tcx List<PlaceElem<'tcx>>, &'tcx List<&'tcx List<PlaceElem<'tcx>>>>,
3179+
{
3180+
T::collect_and_apply(iter, |xs| self.mk_place_elem_chain(xs))
3181+
}
3182+
31723183
pub fn mk_fields_from_iter<I, T>(self, iter: I) -> T::Output
31733184
where
31743185
I: Iterator<Item = T>,

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,7 @@ macro_rules! list_fold {
797797
list_fold! {
798798
&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
799799
&'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
800+
&'tcx ty::List<&'tcx ty::List<PlaceElem<'tcx>>> : mk_place_elem_chain,
800801
&'tcx ty::List<ty::Pattern<'tcx>> : mk_patterns,
801802
&'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>> : mk_outlives,
802803
}

0 commit comments

Comments
 (0)