@@ -581,8 +581,9 @@ pub struct CompoundPlace<'tcx> {
581581#[ derive( Clone , Copy , PartialEq , Eq , Hash ) ]
582582pub 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