@@ -73,27 +73,30 @@ pub enum PlaceBase {
73
73
Upvar ( ty:: UpvarId ) ,
74
74
}
75
75
76
- #[ derive( Clone , Debug ) ]
77
- pub enum ProjectionKind < ' tcx > {
76
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
77
+ pub enum ProjectionKind {
78
78
/// A dereference of a pointer, reference or `Box<T>` of the given type
79
- Deref ( Ty < ' tcx > ) ,
79
+ Deref ,
80
80
/// An index or a field
81
81
Other ,
82
82
}
83
83
84
84
#[ derive( Clone , Debug ) ]
85
85
pub struct Projection < ' tcx > {
86
+ // Type after the projection is being applied.
87
+ ty : Ty < ' tcx > ,
88
+
86
89
/// Defines the type of access
87
- kind : ProjectionKind < ' tcx > ,
90
+ kind : ProjectionKind ,
88
91
}
89
92
90
93
/// A `Place` represents how a value is located in memory.
91
94
///
92
95
/// This is an HIR version of `mir::Place`
93
96
#[ derive( Clone , Debug ) ]
94
97
pub 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 > ,
97
100
/// The "outermost" place that holds this value.
98
101
pub base : PlaceBase ,
99
102
/// How this place is derived from the base place.
@@ -115,13 +118,13 @@ pub struct PlaceWithHirId<'tcx> {
115
118
impl < ' tcx > PlaceWithHirId < ' tcx > {
116
119
crate fn new (
117
120
hir_id : hir:: HirId ,
118
- ty : Ty < ' tcx > ,
121
+ base_ty : Ty < ' tcx > ,
119
122
base : PlaceBase ,
120
123
projections : Vec < Projection < ' tcx > > ,
121
124
) -> PlaceWithHirId < ' tcx > {
122
125
PlaceWithHirId {
123
126
hir_id : hir_id,
124
- place : Place { ty : ty , base : base, projections : projections } ,
127
+ place : Place { base_ty : base_ty , base : base, projections : projections } ,
125
128
}
126
129
}
127
130
}
@@ -134,10 +137,26 @@ impl<'tcx> Place<'tcx> {
134
137
/// `x: &*const u32` and the `Place` is `**x`, then the types returned are
135
138
///`*const u32` then `&*const u32`.
136
139
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
+ }
139
146
} )
140
147
}
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
+ }
141
160
}
142
161
143
162
crate trait HirNode {
@@ -516,8 +535,13 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
516
535
ty : Ty < ' tcx > ,
517
536
) -> PlaceWithHirId < ' tcx > {
518
537
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
+ ) ;
521
545
debug ! ( "cat_field ret {:?}" , ret) ;
522
546
ret
523
547
}
@@ -552,18 +576,23 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
552
576
) -> McResult < PlaceWithHirId < ' tcx > > {
553
577
debug ! ( "cat_deref: base_place={:?}" , base_place) ;
554
578
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 ) {
557
581
Some ( mt) => mt. ty ,
558
582
None => {
559
- debug ! ( "explicit deref of non-derefable type: {:?}" , base_ty ) ;
583
+ debug ! ( "explicit deref of non-derefable type: {:?}" , base_curr_ty ) ;
560
584
return Err ( ( ) ) ;
561
585
}
562
586
} ;
563
587
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
+ ) ;
567
596
debug ! ( "cat_deref ret {:?}" , ret) ;
568
597
Ok ( ret)
569
598
}
@@ -687,7 +716,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
687
716
}
688
717
689
718
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 ( ) {
691
720
Some ( ty) => ty,
692
721
None => {
693
722
debug ! ( "explicit index of non-indexable type {:?}" , place_with_id) ;
0 commit comments