Skip to content

Commit 4d24341

Browse files
authored
Rollup merge of rust-lang#73870 - sexxi-goose:projection-ty, r=nikomatsakis
typeck: adding type information to projection This commit modifies the Place as follow: * remove 'ty' from ProjectionKind * add type information into to Projection * replace 'ty' in Place with 'base_ty' * introduce 'ty()' in `Place` to return the final type of the `Place` * introduce `ty_before_projection()` in `Place` to return the type of a `Place` before i'th projection is applied Closes rust-lang/project-rfc-2229#5
2 parents 99fc337 + 7d7221c commit 4d24341

File tree

4 files changed

+54
-25
lines changed

4 files changed

+54
-25
lines changed

src/librustc_typeck/check/regionck.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
488488
) {
489489
if let mc::PlaceBase::Rvalue = place_with_id.place.base {
490490
if place_with_id.place.projections.is_empty() {
491-
let typ = self.resolve_type(place_with_id.place.ty);
491+
let typ = self.resolve_type(place_with_id.place.ty());
492492
let body_id = self.body_id;
493493
let _ = dropck::check_drop_obligations(self, typ, span, body_id);
494494
}
@@ -640,8 +640,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
640640
borrow_kind: ty::BorrowKind,
641641
borrow_place: &mc::PlaceWithHirId<'tcx>,
642642
) {
643-
let origin = infer::DataBorrowed(borrow_place.place.ty, span);
644-
self.type_must_outlive(origin, borrow_place.place.ty, borrow_region);
643+
let origin = infer::DataBorrowed(borrow_place.place.ty(), span);
644+
self.type_must_outlive(origin, borrow_place.place.ty(), borrow_region);
645645

646646
for pointer_ty in borrow_place.place.deref_tys() {
647647
debug!(

src/librustc_typeck/expr_use_visitor.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
384384

385385
// Select just those fields of the `with`
386386
// expression that will actually be used
387-
match with_place.place.ty.kind {
387+
match with_place.place.ty().kind {
388388
ty::Adt(adt, substs) if adt.is_struct() => {
389389
// Consume those fields of the with expression that are needed.
390390
for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
@@ -583,7 +583,7 @@ fn copy_or_move<'a, 'tcx>(
583583
place_with_id: &PlaceWithHirId<'tcx>,
584584
) -> ConsumeMode {
585585
if !mc.type_is_copy_modulo_regions(
586-
place_with_id.place.ty,
586+
place_with_id.place.ty(),
587587
mc.tcx().hir().span(place_with_id.hir_id),
588588
) {
589589
Move

src/librustc_typeck/mem_categorization.rs

+48-19
Original file line numberDiff line numberDiff line change
@@ -73,27 +73,30 @@ pub enum PlaceBase {
7373
Upvar(ty::UpvarId),
7474
}
7575

76-
#[derive(Clone, Debug)]
77-
pub enum ProjectionKind<'tcx> {
76+
#[derive(Clone, Debug, Eq, PartialEq)]
77+
pub enum ProjectionKind {
7878
/// A dereference of a pointer, reference or `Box<T>` of the given type
79-
Deref(Ty<'tcx>),
79+
Deref,
8080
/// An index or a field
8181
Other,
8282
}
8383

8484
#[derive(Clone, Debug)]
8585
pub struct Projection<'tcx> {
86+
// Type after the projection is being applied.
87+
ty: Ty<'tcx>,
88+
8689
/// Defines the type of access
87-
kind: ProjectionKind<'tcx>,
90+
kind: ProjectionKind,
8891
}
8992

9093
/// A `Place` represents how a value is located in memory.
9194
///
9295
/// This is an HIR version of `mir::Place`
9396
#[derive(Clone, Debug)]
9497
pub struct Place<'tcx> {
95-
/// The type of the `Place`
96-
pub ty: Ty<'tcx>,
98+
/// The type of the `PlaceBase`
99+
pub base_ty: Ty<'tcx>,
97100
/// The "outermost" place that holds this value.
98101
pub base: PlaceBase,
99102
/// How this place is derived from the base place.
@@ -115,13 +118,13 @@ pub struct PlaceWithHirId<'tcx> {
115118
impl<'tcx> PlaceWithHirId<'tcx> {
116119
crate fn new(
117120
hir_id: hir::HirId,
118-
ty: Ty<'tcx>,
121+
base_ty: Ty<'tcx>,
119122
base: PlaceBase,
120123
projections: Vec<Projection<'tcx>>,
121124
) -> PlaceWithHirId<'tcx> {
122125
PlaceWithHirId {
123126
hir_id: hir_id,
124-
place: Place { ty: ty, base: base, projections: projections },
127+
place: Place { base_ty: base_ty, base: base, projections: projections },
125128
}
126129
}
127130
}
@@ -134,10 +137,26 @@ impl<'tcx> Place<'tcx> {
134137
/// `x: &*const u32` and the `Place` is `**x`, then the types returned are
135138
///`*const u32` then `&*const u32`.
136139
crate fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
137-
self.projections.iter().rev().filter_map(|proj| {
138-
if let ProjectionKind::Deref(deref_ty) = proj.kind { Some(deref_ty) } else { None }
140+
self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
141+
if ProjectionKind::Deref == proj.kind {
142+
Some(self.ty_before_projection(index))
143+
} else {
144+
None
145+
}
139146
})
140147
}
148+
149+
// Returns the type of this `Place` after all projections have been applied.
150+
pub fn ty(&self) -> Ty<'tcx> {
151+
self.projections.last().map_or_else(|| self.base_ty, |proj| proj.ty)
152+
}
153+
154+
// Returns the type of this `Place` immediately before `projection_index`th projection
155+
// is applied.
156+
crate fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> {
157+
assert!(projection_index < self.projections.len());
158+
if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty }
159+
}
141160
}
142161

143162
crate trait HirNode {
@@ -516,8 +535,13 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
516535
ty: Ty<'tcx>,
517536
) -> PlaceWithHirId<'tcx> {
518537
let mut projections = base_place.place.projections;
519-
projections.push(Projection { kind: ProjectionKind::Other });
520-
let ret = PlaceWithHirId::new(node.hir_id(), ty, base_place.place.base, projections);
538+
projections.push(Projection { kind: ProjectionKind::Other, ty: ty });
539+
let ret = PlaceWithHirId::new(
540+
node.hir_id(),
541+
base_place.place.base_ty,
542+
base_place.place.base,
543+
projections,
544+
);
521545
debug!("cat_field ret {:?}", ret);
522546
ret
523547
}
@@ -552,18 +576,23 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
552576
) -> McResult<PlaceWithHirId<'tcx>> {
553577
debug!("cat_deref: base_place={:?}", base_place);
554578

555-
let base_ty = base_place.place.ty;
556-
let deref_ty = match base_ty.builtin_deref(true) {
579+
let base_curr_ty = base_place.place.ty();
580+
let deref_ty = match base_curr_ty.builtin_deref(true) {
557581
Some(mt) => mt.ty,
558582
None => {
559-
debug!("explicit deref of non-derefable type: {:?}", base_ty);
583+
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
560584
return Err(());
561585
}
562586
};
563587
let mut projections = base_place.place.projections;
564-
projections.push(Projection { kind: ProjectionKind::Deref(base_ty) });
565-
566-
let ret = PlaceWithHirId::new(node.hir_id(), deref_ty, base_place.place.base, projections);
588+
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
589+
590+
let ret = PlaceWithHirId::new(
591+
node.hir_id(),
592+
base_place.place.base_ty,
593+
base_place.place.base,
594+
projections,
595+
);
567596
debug!("cat_deref ret {:?}", ret);
568597
Ok(ret)
569598
}
@@ -687,7 +716,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
687716
}
688717

689718
PatKind::Slice(before, ref slice, after) => {
690-
let element_ty = match place_with_id.place.ty.builtin_index() {
719+
let element_ty = match place_with_id.place.ty().builtin_index() {
691720
Some(ty) => ty,
692721
None => {
693722
debug!("explicit index of non-indexable type {:?}", place_with_id);

src/tools/clippy/clippy_lints/src/escape.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
150150
return;
151151
}
152152

153-
if is_non_trait_box(cmt.place.ty) && !self.is_large_box(cmt.place.ty) {
153+
if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
154154
self.set.insert(cmt.hir_id);
155155
}
156156
return;

0 commit comments

Comments
 (0)