1 use crate::ty; 2 use crate::ty::Ty; 3 4 use rustc_hir::HirId; 5 use rustc_target::abi::VariantIdx; 6 7 #[derive( 8 Clone, 9 Copy, 10 Debug, 11 PartialEq, 12 Eq, 13 Hash, 14 TyEncodable, 15 TyDecodable, 16 TypeFoldable, 17 HashStable 18 )] 19 pub enum PlaceBase { 20 /// A temporary variable. 21 Rvalue, 22 /// A named `static` item. 23 StaticItem, 24 /// A named local variable. 25 Local(HirId), 26 /// An upvar referenced by closure env. 27 Upvar(ty::UpvarId), 28 } 29 30 #[derive( 31 Clone, 32 Copy, 33 Debug, 34 PartialEq, 35 Eq, 36 Hash, 37 TyEncodable, 38 TyDecodable, 39 TypeFoldable, 40 HashStable 41 )] 42 pub enum ProjectionKind { 43 /// A dereference of a pointer, reference or `Box<T>` of the given type. 44 Deref, 45 46 /// `B.F` where `B` is the base expression and `F` is 47 /// the field. The field is identified by which variant 48 /// it appears in along with a field index. The variant 49 /// is used for enums. 50 Field(u32, VariantIdx), 51 52 /// Some index like `B[x]`, where `B` is the base 53 /// expression. We don't preserve the index `x` because 54 /// we won't need it. 55 Index, 56 57 /// A subslice covering a range of values like `B[x..y]`. 58 Subslice, 59 } 60 61 #[derive( 62 Clone, 63 Copy, 64 Debug, 65 PartialEq, 66 Eq, 67 Hash, 68 TyEncodable, 69 TyDecodable, 70 TypeFoldable, 71 HashStable 72 )] 73 pub struct Projection<'tcx> { 74 /// Type after the projection is applied. 75 pub ty: Ty<'tcx>, 76 77 /// Defines the kind of access made by the projection. 78 pub kind: ProjectionKind, 79 } 80 81 /// A `Place` represents how a value is located in memory. 82 /// 83 /// This is an HIR version of [`rustc_middle::mir::Place`]. 84 #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] 85 pub struct Place<'tcx> { 86 /// The type of the `PlaceBase` 87 pub base_ty: Ty<'tcx>, 88 /// The "outermost" place that holds this value. 89 pub base: PlaceBase, 90 /// How this place is derived from the base place. 91 pub projections: Vec<Projection<'tcx>>, 92 } 93 94 /// A `PlaceWithHirId` represents how a value is located in memory. 95 /// 96 /// This is an HIR version of [`rustc_middle::mir::Place`]. 97 #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] 98 pub struct PlaceWithHirId<'tcx> { 99 /// `HirId` of the expression or pattern producing this value. 100 pub hir_id: HirId, 101 102 /// Information about the `Place`. 103 pub place: Place<'tcx>, 104 } 105 106 impl<'tcx> PlaceWithHirId<'tcx> { new( hir_id: HirId, base_ty: Ty<'tcx>, base: PlaceBase, projections: Vec<Projection<'tcx>>, ) -> PlaceWithHirId<'tcx>107 pub fn new( 108 hir_id: HirId, 109 base_ty: Ty<'tcx>, 110 base: PlaceBase, 111 projections: Vec<Projection<'tcx>>, 112 ) -> PlaceWithHirId<'tcx> { 113 PlaceWithHirId { hir_id, place: Place { base_ty, base, projections } } 114 } 115 } 116 117 impl<'tcx> Place<'tcx> { 118 /// Returns an iterator of the types that have to be dereferenced to access 119 /// the `Place`. 120 /// 121 /// The types are in the reverse order that they are applied. So if 122 /// `x: &*const u32` and the `Place` is `**x`, then the types returned are 123 ///`*const u32` then `&*const u32`. deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_124 pub fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ { 125 self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| { 126 if ProjectionKind::Deref == proj.kind { 127 Some(self.ty_before_projection(index)) 128 } else { 129 None 130 } 131 }) 132 } 133 134 /// Returns the type of this `Place` after all projections have been applied. ty(&self) -> Ty<'tcx>135 pub fn ty(&self) -> Ty<'tcx> { 136 self.projections.last().map_or(self.base_ty, |proj| proj.ty) 137 } 138 139 /// Returns the type of this `Place` immediately before `projection_index`th projection 140 /// is applied. ty_before_projection(&self, projection_index: usize) -> Ty<'tcx>141 pub fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> { 142 assert!(projection_index < self.projections.len()); 143 if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty } 144 } 145 } 146