]> git.proxmox.com Git - rustc.git/blame - src/librustc_middle/hir/place.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_middle / hir / place.rs
CommitLineData
3dfed10e
XL
1use crate::ty;
2use crate::ty::Ty;
3
4use rustc_hir::HirId;
5use rustc_target::abi::VariantIdx;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
8pub 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)]
20pub 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)]
40pub 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)]
52pub 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)]
65pub 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
73impl<'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
87impl<'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}