@@ -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