]> git.lizzy.rs Git - rust.git/blob - src/librustc_middle/hir/place.rs
pin docs: add some forward references
[rust.git] / src / librustc_middle / 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, RustcEncodable, RustcDecodable, 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, RustcEncodable, RustcDecodable, 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, RustcEncodable, RustcDecodable, 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, RustcEncodable, RustcDecodable, 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, RustcEncodable, RustcDecodable, 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 }