5 use rustc_target::abi::VariantIdx;
20 /// A temporary variable.
22 /// A named `static` item.
24 /// A named local variable.
26 /// An upvar referenced by closure env.
42 pub enum ProjectionKind {
43 /// A dereference of a pointer, reference or `Box<T>` of the given type.
46 /// `B.F` where `B` is the base expression and `F` is
47 /// the field. The field is identified by which variant
48 /// it appears in along with a field index. The variant
49 /// is used for enums.
50 Field(u32, VariantIdx),
52 /// Some index like `B[x]`, where `B` is the base
53 /// expression. We don't preserve the index `x` because
57 /// A subslice covering a range of values like `B[x..y]`.
73 pub struct Projection<'tcx> {
74 /// Type after the projection is applied.
77 /// Defines the kind of access made by the projection.
78 pub kind: ProjectionKind,
81 /// A `Place` represents how a value is located in memory.
83 /// This is an HIR version of [`rustc_middle::mir::Place`].
84 #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
85 pub struct Place<'tcx> {
86 /// The type of the `PlaceBase`
87 pub base_ty: Ty<'tcx>,
88 /// The "outermost" place that holds this value.
90 /// How this place is derived from the base place.
91 pub projections: Vec<Projection<'tcx>>,
94 /// A `PlaceWithHirId` represents how a value is located in memory.
96 /// This is an HIR version of [`rustc_middle::mir::Place`].
97 #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
98 pub struct PlaceWithHirId<'tcx> {
99 /// `HirId` of the expression or pattern producing this value.
102 /// Information about the `Place`.
103 pub place: Place<'tcx>,
106 impl<'tcx> PlaceWithHirId<'tcx> {
111 projections: Vec<Projection<'tcx>>,
112 ) -> PlaceWithHirId<'tcx> {
113 PlaceWithHirId { hir_id, place: Place { base_ty, base, projections } }
117 impl<'tcx> Place<'tcx> {
118 /// Returns an iterator of the types that have to be dereferenced to access
121 /// The types are in the reverse order that they are applied. So if
122 /// `x: &*const u32` and the `Place` is `**x`, then the types returned are
123 ///`*const u32` then `&*const u32`.
124 pub fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
125 self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
126 if ProjectionKind::Deref == proj.kind {
127 Some(self.ty_before_projection(index))
134 /// Returns the type of this `Place` after all projections have been applied.
135 pub fn ty(&self) -> Ty<'tcx> {
136 self.projections.last().map_or(self.base_ty, |proj| proj.ty)
139 /// Returns the type of this `Place` immediately before `projection_index`th projection
141 pub fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> {
142 assert!(projection_index < self.projections.len());
143 if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty }