Skip to content

Commit 2759170

Browse files
committed
tighter representation of CompoundPlaceRef
1 parent 188243b commit 2759170

File tree

2 files changed

+49
-52
lines changed

2 files changed

+49
-52
lines changed

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,17 +1278,19 @@ impl Debug for CompoundPlace<'_> {
12781278

12791279
impl Debug for CompoundPlaceRef<'_> {
12801280
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() {
1281+
let (stem, suffix) = self.projection_chain.unwrap_or_default();
1282+
1283+
pre_fmt_projection(suffix, fmt)?;
1284+
for projection in stem.iter().rev() {
12831285
pre_fmt_projection(projection, fmt)?;
12841286
}
12851287

12861288
write!(fmt, "{:?}", self.local)?;
12871289

1288-
for projection in self.projection_chain_base {
1290+
for projection in stem {
12891291
post_fmt_projection(projection, fmt)?;
12901292
}
1291-
post_fmt_projection(self.last_projection, fmt)?;
1293+
post_fmt_projection(suffix, fmt)?;
12921294

12931295
Ok(())
12941296
}

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 43 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -581,8 +581,9 @@ pub struct CompoundPlace<'tcx> {
581581
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
582582
pub struct CompoundPlaceRef<'tcx> {
583583
pub local: Local,
584-
pub projection_chain_base: &'tcx [ProjectionFragment<'tcx>],
585-
pub last_projection: ProjectionFragmentRef<'tcx>,
584+
/// `None` is equivalent to an empty projection chain,
585+
/// `Some((stem, suffix))` is equivalent to `stem` with `suffix` appended to it
586+
pub projection_chain: Option<(&'tcx [ProjectionFragment<'tcx>], ProjectionFragmentRef<'tcx>)>,
586587
}
587588

588589
// these impls are bare-bones for now
@@ -617,13 +618,7 @@ impl<'tcx> CompoundPlace<'tcx> {
617618
}
618619

619620
pub fn as_ref(&self) -> CompoundPlaceRef<'tcx> {
620-
let (last, base) = self
621-
.projection_chain
622-
.split_last()
623-
.map(|(&last, base)| (last, base))
624-
.unwrap_or_default();
625-
626-
CompoundPlaceRef { local: self.local, projection_chain_base: base, last_projection: last }
621+
CompoundPlaceRef::from_slice(self.local, self.projection_chain)
627622
}
628623

629624
pub fn as_local(&self) -> Option<Local> {
@@ -684,37 +679,11 @@ impl<'tcx> CompoundPlace<'tcx> {
684679
) -> impl Iterator<Item = (CompoundPlaceRef<'tcx>, PlaceElem<'tcx>)> + DoubleEndedIterator {
685680
self.projection_chain.iter().enumerate().flat_map(move |(i, projs)| {
686681
projs.iter().enumerate().map(move |(j, elem)| {
687-
let base = if j == 0 && i > 0 {
688-
// last_projection should only be empty if projection_chain_base is too
689-
debug_assert_eq!(elem, PlaceElem::Deref);
690-
CompoundPlaceRef {
691-
local: self.local,
692-
projection_chain_base: &self.projection_chain[..i - 1],
693-
last_projection: &self.projection_chain[i - 1],
694-
}
695-
696-
// FIXME: the fact that i messed up this logic the first time is good evidence that
697-
// the invariants are confusing and difficult to uphold
698-
} else {
699-
CompoundPlaceRef {
700-
local: self.local,
701-
projection_chain_base: &self.projection_chain[..i],
702-
last_projection: &projs[..j],
703-
}
704-
};
705-
706-
if cfg!(debug_assertions) {
707-
let self_projections: Vec<_> = self.projection_chain.iter().flatten().collect();
708-
let base_projections: Vec<_> = base
709-
.projection_chain_base
710-
.iter()
711-
.copied()
712-
.flatten()
713-
.chain(base.last_projection.iter().copied())
714-
.collect();
715-
716-
assert_eq!(self_projections[..base_projections.len()], base_projections);
717-
}
682+
let base = CompoundPlaceRef::from_stem_with_suffix(
683+
self.local,
684+
&self.projection_chain[..i],
685+
&projs[..j],
686+
);
718687

719688
(base, elem)
720689
})
@@ -742,21 +711,47 @@ impl<'tcx> CompoundPlaceRef<'tcx> {
742711
where
743712
D: HasLocalDecls<'tcx>,
744713
{
745-
PlaceTy::from_ty(local_decls.local_decls()[self.local].ty)
746-
.projection_chain_ty(tcx, self.projection_chain_base)
747-
.multi_projection_ty(tcx, self.last_projection)
714+
let local_ty = PlaceTy::from_ty(local_decls.local_decls()[self.local].ty);
715+
716+
match self.projection_chain {
717+
Some((stem, suffix)) => {
718+
local_ty.projection_chain_ty(tcx, stem).multi_projection_ty(tcx, suffix)
719+
}
720+
None => local_ty,
721+
}
748722
}
749723

750724
pub fn local_or_deref_local(&self) -> Option<Local> {
751725
match *self {
752-
CompoundPlaceRef {
753-
local,
754-
projection_chain_base: [],
755-
last_projection: [] | [ProjectionElem::Deref],
756-
} => Some(local),
726+
CompoundPlaceRef { local, projection_chain: None | Some(([], [PlaceElem::Deref])) } => {
727+
Some(local)
728+
}
757729
_ => None,
758730
}
759731
}
732+
733+
fn from_slice(local: Local, chain: &'tcx [ProjectionFragment<'tcx>]) -> CompoundPlaceRef<'tcx> {
734+
let projection_chain = match chain {
735+
[stem @ .., suffix] => Some((stem, suffix.as_slice())),
736+
[] => None,
737+
};
738+
739+
CompoundPlaceRef { local, projection_chain }
740+
}
741+
742+
fn from_stem_with_suffix(
743+
local: Local,
744+
stem: &'tcx [ProjectionFragment<'tcx>],
745+
suffix: ProjectionFragmentRef<'tcx>,
746+
) -> CompoundPlaceRef<'tcx> {
747+
let projection_chain = match (stem, suffix) {
748+
([], []) => None,
749+
([stem @ .., suffix], []) => Some((stem, suffix.as_slice())),
750+
_ => Some((stem, suffix)),
751+
};
752+
753+
CompoundPlaceRef { local, projection_chain }
754+
}
760755
}
761756

762757
///////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)