rustc_middle/hir/
place.rs1use rustc_abi::{FieldIdx, VariantIdx};
2use rustc_hir::HirId;
3use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
4
5use crate::ty;
6use crate::ty::Ty;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
9#[derive(TypeFoldable, TypeVisitable)]
10pub enum PlaceBase {
11 Rvalue,
13 StaticItem,
15 Local(HirId),
17 Upvar(ty::UpvarId),
19}
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
22#[derive(TypeFoldable, TypeVisitable)]
23pub enum ProjectionKind {
24 Deref,
26
27 Field(FieldIdx, VariantIdx),
32
33 Index,
37
38 Subslice,
40
41 OpaqueCast,
44}
45
46#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
47#[derive(TypeFoldable, TypeVisitable)]
48pub struct Projection<'tcx> {
49 pub ty: Ty<'tcx>,
51
52 pub kind: ProjectionKind,
54}
55
56#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
60#[derive(TypeFoldable, TypeVisitable)]
61pub struct Place<'tcx> {
62 pub base_ty: Ty<'tcx>,
64 pub base: PlaceBase,
66 pub projections: Vec<Projection<'tcx>>,
68}
69
70#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
74pub struct PlaceWithHirId<'tcx> {
75 pub hir_id: HirId,
77
78 pub place: Place<'tcx>,
80}
81
82impl<'tcx> PlaceWithHirId<'tcx> {
83 pub fn new(
84 hir_id: HirId,
85 base_ty: Ty<'tcx>,
86 base: PlaceBase,
87 projections: Vec<Projection<'tcx>>,
88 ) -> PlaceWithHirId<'tcx> {
89 PlaceWithHirId { hir_id, place: Place { base_ty, base, projections } }
90 }
91}
92
93impl<'tcx> Place<'tcx> {
94 pub fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> {
101 self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
102 if ProjectionKind::Deref == proj.kind {
103 Some(self.ty_before_projection(index))
104 } else {
105 None
106 }
107 })
108 }
109
110 pub fn ty(&self) -> Ty<'tcx> {
112 self.projections.last().map_or(self.base_ty, |proj| proj.ty)
113 }
114
115 pub fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> {
118 assert!(projection_index < self.projections.len());
119 if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty }
120 }
121}