@@ -73,27 +73,30 @@ pub enum PlaceBase {
7373     Upvar ( ty:: UpvarId ) , 
7474} 
7575
76- #[ derive( Clone ,  Debug ) ]  
77- pub  enum  ProjectionKind < ' tcx >  { 
76+ #[ derive( Clone ,  Debug ,   Eq ,   PartialEq ) ]  
77+ pub  enum  ProjectionKind  { 
7878    /// A dereference of a pointer, reference or `Box<T>` of the given type 
79-      Deref ( Ty < ' tcx > ) , 
79+      Deref , 
8080    /// An index or a field 
8181     Other , 
8282} 
8383
8484#[ derive( Clone ,  Debug ) ]  
8585pub  struct  Projection < ' tcx >  { 
86+     // Type after the projection is being applied. 
87+     ty :  Ty < ' tcx > , 
88+ 
8689    /// Defines the type of access 
87-      kind :  ProjectionKind < ' tcx > , 
90+      kind :  ProjectionKind , 
8891} 
8992
9093/// A `Place` represents how a value is located in memory. 
9194/// 
9295/// This is an HIR version of `mir::Place` 
9396#[ derive( Clone ,  Debug ) ]  
9497pub  struct  Place < ' tcx >  { 
95-     /// The type of the `Place ` 
96-      pub  ty :  Ty < ' tcx > , 
98+     /// The type of the `PlaceBase ` 
99+      pub  base_ty :  Ty < ' tcx > , 
97100    /// The "outermost" place that holds this value. 
98101     pub  base :  PlaceBase , 
99102    /// How this place is derived from the base place. 
@@ -115,13 +118,13 @@ pub struct PlaceWithHirId<'tcx> {
115118impl < ' tcx >  PlaceWithHirId < ' tcx >  { 
116119    crate  fn  new ( 
117120        hir_id :  hir:: HirId , 
118-         ty :  Ty < ' tcx > , 
121+         base_ty :  Ty < ' tcx > , 
119122        base :  PlaceBase , 
120123        projections :  Vec < Projection < ' tcx > > , 
121124    )  -> PlaceWithHirId < ' tcx >  { 
122125        PlaceWithHirId  { 
123126            hir_id :  hir_id, 
124-             place :  Place  {  ty :  ty ,  base :  base,  projections :  projections } , 
127+             place :  Place  {  base_ty :  base_ty ,  base :  base,  projections :  projections } , 
125128        } 
126129    } 
127130} 
@@ -134,10 +137,26 @@ impl<'tcx> Place<'tcx> {
134137     /// `x: &*const u32` and the `Place` is `**x`, then the types returned are 
135138     ///`*const u32` then `&*const u32`. 
136139     crate  fn  deref_tys ( & self )  -> impl  Iterator < Item  = Ty < ' tcx > >  + ' _  { 
137-         self . projections . iter ( ) . rev ( ) . filter_map ( |proj| { 
138-             if  let  ProjectionKind :: Deref ( deref_ty)  = proj. kind  {  Some ( deref_ty)  }  else  {  None  } 
140+         self . projections . iter ( ) . enumerate ( ) . rev ( ) . filter_map ( move  |( index,  proj) | { 
141+             if  ProjectionKind :: Deref  == proj. kind  { 
142+                 Some ( self . ty_before_projection ( index) ) 
143+             }  else  { 
144+                 None 
145+             } 
139146        } ) 
140147    } 
148+ 
149+     // Returns the type of this `Place` after all projections have been applied. 
150+     pub  fn  ty ( & self )  -> Ty < ' tcx >  { 
151+         self . projections . last ( ) . map_or_else ( || self . base_ty ,  |proj| proj. ty ) 
152+     } 
153+ 
154+     // Returns the type of this `Place` immediately before `projection_index`th projection 
155+     // is applied. 
156+     crate  fn  ty_before_projection ( & self ,  projection_index :  usize )  -> Ty < ' tcx >  { 
157+         assert ! ( projection_index < self . projections. len( ) ) ; 
158+         if  projection_index == 0  {  self . base_ty  }  else  {  self . projections [ projection_index - 1 ] . ty  } 
159+     } 
141160} 
142161
143162crate  trait  HirNode  { 
@@ -516,8 +535,13 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
516535        ty :  Ty < ' tcx > , 
517536    )  -> PlaceWithHirId < ' tcx >  { 
518537        let  mut  projections = base_place. place . projections ; 
519-         projections. push ( Projection  {  kind :  ProjectionKind :: Other  } ) ; 
520-         let  ret = PlaceWithHirId :: new ( node. hir_id ( ) ,  ty,  base_place. place . base ,  projections) ; 
538+         projections. push ( Projection  {  kind :  ProjectionKind :: Other ,  ty :  ty } ) ; 
539+         let  ret = PlaceWithHirId :: new ( 
540+             node. hir_id ( ) , 
541+             base_place. place . base_ty , 
542+             base_place. place . base , 
543+             projections, 
544+         ) ; 
521545        debug ! ( "cat_field ret {:?}" ,  ret) ; 
522546        ret
523547    } 
@@ -552,18 +576,23 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
552576    )  -> McResult < PlaceWithHirId < ' tcx > >  { 
553577        debug ! ( "cat_deref: base_place={:?}" ,  base_place) ; 
554578
555-         let  base_ty  = base_place. place . ty ; 
556-         let  deref_ty = match  base_ty . builtin_deref ( true )  { 
579+         let  base_curr_ty  = base_place. place . ty ( ) ; 
580+         let  deref_ty = match  base_curr_ty . builtin_deref ( true )  { 
557581            Some ( mt)  => mt. ty , 
558582            None  => { 
559-                 debug ! ( "explicit deref of non-derefable type: {:?}" ,  base_ty ) ; 
583+                 debug ! ( "explicit deref of non-derefable type: {:?}" ,  base_curr_ty ) ; 
560584                return  Err ( ( ) ) ; 
561585            } 
562586        } ; 
563587        let  mut  projections = base_place. place . projections ; 
564-         projections. push ( Projection  {  kind :  ProjectionKind :: Deref ( base_ty)  } ) ; 
565- 
566-         let  ret = PlaceWithHirId :: new ( node. hir_id ( ) ,  deref_ty,  base_place. place . base ,  projections) ; 
588+         projections. push ( Projection  {  kind :  ProjectionKind :: Deref ,  ty :  deref_ty } ) ; 
589+ 
590+         let  ret = PlaceWithHirId :: new ( 
591+             node. hir_id ( ) , 
592+             base_place. place . base_ty , 
593+             base_place. place . base , 
594+             projections, 
595+         ) ; 
567596        debug ! ( "cat_deref ret {:?}" ,  ret) ; 
568597        Ok ( ret) 
569598    } 
@@ -687,7 +716,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
687716            } 
688717
689718            PatKind :: Slice ( before,  ref  slice,  after)  => { 
690-                 let  element_ty = match  place_with_id. place . ty . builtin_index ( )  { 
719+                 let  element_ty = match  place_with_id. place . ty ( ) . builtin_index ( )  { 
691720                    Some ( ty)  => ty, 
692721                    None  => { 
693722                        debug ! ( "explicit index of non-indexable type {:?}" ,  place_with_id) ; 
0 commit comments