1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use crate::ty;
use crate::ty::Ty;
use rustc_hir::HirId;
use rustc_target::abi::VariantIdx;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum PlaceBase {
Rvalue,
StaticItem,
Local(HirId),
Upvar(ty::UpvarId),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum ProjectionKind {
Deref,
Field(u32, VariantIdx),
Index,
Subslice,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct Projection<'tcx> {
pub ty: Ty<'tcx>,
pub kind: ProjectionKind,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct Place<'tcx> {
pub base_ty: Ty<'tcx>,
pub base: PlaceBase,
pub projections: Vec<Projection<'tcx>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct PlaceWithHirId<'tcx> {
pub hir_id: HirId,
pub place: Place<'tcx>,
}
impl<'tcx> PlaceWithHirId<'tcx> {
pub fn new(
hir_id: HirId,
base_ty: Ty<'tcx>,
base: PlaceBase,
projections: Vec<Projection<'tcx>>,
) -> PlaceWithHirId<'tcx> {
PlaceWithHirId { hir_id, place: Place { base_ty, base, projections } }
}
}
impl<'tcx> Place<'tcx> {
pub fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
if ProjectionKind::Deref == proj.kind {
Some(self.ty_before_projection(index))
} else {
None
}
})
}
pub fn ty(&self) -> Ty<'tcx> {
self.projections.last().map_or(self.base_ty, |proj| proj.ty)
}
pub fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> {
assert!(projection_index < self.projections.len());
if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty }
}
}