1use rustc_abi::{FieldIdx, VariantIdx};
2use rustc_hir::HirId;
3use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
45use crate::ty;
6use crate::ty::Ty;
78#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
9#[derive(TypeFoldable, TypeVisitable)]
10pub enum PlaceBase {
11/// A temporary variable.
12Rvalue,
13/// A named `static` item.
14StaticItem,
15/// A named local variable.
16Local(HirId),
17/// An upvar referenced by closure env.
18Upvar(ty::UpvarId),
19}
2021#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
22#[derive(TypeFoldable, TypeVisitable)]
23pub enum ProjectionKind {
24/// A dereference of a pointer, reference or `Box<T>` of the given type.
25Deref,
2627/// `B.F` where `B` is the base expression and `F` is
28 /// the field. The field is identified by which variant
29 /// it appears in along with a field index. The variant
30 /// is used for enums.
31Field(FieldIdx, VariantIdx),
3233/// Some index like `B[x]`, where `B` is the base
34 /// expression. We don't preserve the index `x` because
35 /// we won't need it.
36Index,
3738/// A subslice covering a range of values like `B[x..y]`.
39Subslice,
4041/// A conversion from an opaque type to its hidden type so we can
42 /// do further projections on it.
43OpaqueCast,
44}
4546#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
47#[derive(TypeFoldable, TypeVisitable)]
48pub struct Projection<'tcx> {
49/// Type after the projection is applied.
50pub ty: Ty<'tcx>,
5152/// Defines the kind of access made by the projection.
53pub kind: ProjectionKind,
54}
5556/// A `Place` represents how a value is located in memory.
57///
58/// This is an HIR version of [`rustc_middle::mir::Place`].
59#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
60#[derive(TypeFoldable, TypeVisitable)]
61pub struct Place<'tcx> {
62/// The type of the `PlaceBase`
63pub base_ty: Ty<'tcx>,
64/// The "outermost" place that holds this value.
65pub base: PlaceBase,
66/// How this place is derived from the base place.
67pub projections: Vec<Projection<'tcx>>,
68}
6970/// A `PlaceWithHirId` represents how a value is located in memory.
71///
72/// This is an HIR version of [`rustc_middle::mir::Place`].
73#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
74pub struct PlaceWithHirId<'tcx> {
75/// `HirId` of the expression or pattern producing this value.
76pub hir_id: HirId,
7778/// Information about the `Place`.
79pub place: Place<'tcx>,
80}
8182impl<'tcx> PlaceWithHirId<'tcx> {
83pub fn new(
84 hir_id: HirId,
85 base_ty: Ty<'tcx>,
86 base: PlaceBase,
87 projections: Vec<Projection<'tcx>>,
88 ) -> PlaceWithHirId<'tcx> {
89PlaceWithHirId { hir_id, place: Place { base_ty, base, projections } }
90 }
91}
9293impl<'tcx> Place<'tcx> {
94/// Returns an iterator of the types that have to be dereferenced to access
95 /// the `Place`.
96 ///
97 /// The types are in the reverse order that they are applied. So if
98 /// `x: &*const u32` and the `Place` is `**x`, then the types returned are
99 ///`*const u32` then `&*const u32`.
100pub fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> {
101self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
102if ProjectionKind::Deref == proj.kind {
103Some(self.ty_before_projection(index))
104 } else {
105None106 }
107 })
108 }
109110/// Returns the type of this `Place` after all projections have been applied.
111pub fn ty(&self) -> Ty<'tcx> {
112self.projections.last().map_or(self.base_ty, |proj| proj.ty)
113 }
114115/// Returns the type of this `Place` immediately before `projection_index`th projection
116 /// is applied.
117pub fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> {
118assert!(projection_index < self.projections.len());
119if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty }
120 }
121}