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