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