@@ -581,8 +581,9 @@ pub struct CompoundPlace<'tcx> {
581
581
#[ derive( Clone , Copy , PartialEq , Eq , Hash ) ]
582
582
pub struct CompoundPlaceRef < ' tcx > {
583
583
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 > ) > ,
586
587
}
587
588
588
589
// these impls are bare-bones for now
@@ -617,13 +618,7 @@ impl<'tcx> CompoundPlace<'tcx> {
617
618
}
618
619
619
620
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 )
627
622
}
628
623
629
624
pub fn as_local ( & self ) -> Option < Local > {
@@ -684,37 +679,11 @@ impl<'tcx> CompoundPlace<'tcx> {
684
679
) -> impl Iterator < Item = ( CompoundPlaceRef < ' tcx > , PlaceElem < ' tcx > ) > + DoubleEndedIterator {
685
680
self . projection_chain . iter ( ) . enumerate ( ) . flat_map ( move |( i, projs) | {
686
681
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
+ ) ;
718
687
719
688
( base, elem)
720
689
} )
@@ -742,21 +711,47 @@ impl<'tcx> CompoundPlaceRef<'tcx> {
742
711
where
743
712
D : HasLocalDecls < ' tcx > ,
744
713
{
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
+ }
748
722
}
749
723
750
724
pub fn local_or_deref_local ( & self ) -> Option < Local > {
751
725
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
+ }
757
729
_ => None ,
758
730
}
759
731
}
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
+ }
760
755
}
761
756
762
757
///////////////////////////////////////////////////////////////////////////
0 commit comments