Rollup merge of #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 https://github.com/rust-lang/project-rfc-2229/issues/5
This commit is contained in:
commit
7942d9a65a
@ -488,7 +488,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
) {
|
||||
if let mc::PlaceBase::Rvalue = place_with_id.place.base {
|
||||
if place_with_id.place.projections.is_empty() {
|
||||
let typ = self.resolve_type(place_with_id.place.ty);
|
||||
let typ = self.resolve_type(place_with_id.place.ty());
|
||||
let body_id = self.body_id;
|
||||
let _ = dropck::check_drop_obligations(self, typ, span, body_id);
|
||||
}
|
||||
@ -640,8 +640,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
||||
borrow_kind: ty::BorrowKind,
|
||||
borrow_place: &mc::PlaceWithHirId<'tcx>,
|
||||
) {
|
||||
let origin = infer::DataBorrowed(borrow_place.place.ty, span);
|
||||
self.type_must_outlive(origin, borrow_place.place.ty, borrow_region);
|
||||
let origin = infer::DataBorrowed(borrow_place.place.ty(), span);
|
||||
self.type_must_outlive(origin, borrow_place.place.ty(), borrow_region);
|
||||
|
||||
for pointer_ty in borrow_place.place.deref_tys() {
|
||||
debug!(
|
||||
|
@ -384,7 +384,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
|
||||
// Select just those fields of the `with`
|
||||
// expression that will actually be used
|
||||
match with_place.place.ty.kind {
|
||||
match with_place.place.ty().kind {
|
||||
ty::Adt(adt, substs) if adt.is_struct() => {
|
||||
// Consume those fields of the with expression that are needed.
|
||||
for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
|
||||
@ -583,7 +583,7 @@ fn copy_or_move<'a, 'tcx>(
|
||||
place_with_id: &PlaceWithHirId<'tcx>,
|
||||
) -> ConsumeMode {
|
||||
if !mc.type_is_copy_modulo_regions(
|
||||
place_with_id.place.ty,
|
||||
place_with_id.place.ty(),
|
||||
mc.tcx().hir().span(place_with_id.hir_id),
|
||||
) {
|
||||
Move
|
||||
|
@ -73,18 +73,21 @@ pub enum PlaceBase {
|
||||
Upvar(ty::UpvarId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ProjectionKind<'tcx> {
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ProjectionKind {
|
||||
/// A dereference of a pointer, reference or `Box<T>` of the given type
|
||||
Deref(Ty<'tcx>),
|
||||
Deref,
|
||||
/// An index or a field
|
||||
Other,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Projection<'tcx> {
|
||||
// Type after the projection is being applied.
|
||||
ty: Ty<'tcx>,
|
||||
|
||||
/// Defines the type of access
|
||||
kind: ProjectionKind<'tcx>,
|
||||
kind: ProjectionKind,
|
||||
}
|
||||
|
||||
/// A `Place` represents how a value is located in memory.
|
||||
@ -92,8 +95,8 @@ pub struct Projection<'tcx> {
|
||||
/// This is an HIR version of `mir::Place`
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Place<'tcx> {
|
||||
/// The type of the `Place`
|
||||
pub ty: Ty<'tcx>,
|
||||
/// The type of the `PlaceBase`
|
||||
pub base_ty: Ty<'tcx>,
|
||||
/// The "outermost" place that holds this value.
|
||||
pub base: PlaceBase,
|
||||
/// How this place is derived from the base place.
|
||||
@ -115,13 +118,13 @@ pub struct PlaceWithHirId<'tcx> {
|
||||
impl<'tcx> PlaceWithHirId<'tcx> {
|
||||
crate fn new(
|
||||
hir_id: hir::HirId,
|
||||
ty: Ty<'tcx>,
|
||||
base_ty: Ty<'tcx>,
|
||||
base: PlaceBase,
|
||||
projections: Vec<Projection<'tcx>>,
|
||||
) -> PlaceWithHirId<'tcx> {
|
||||
PlaceWithHirId {
|
||||
hir_id: hir_id,
|
||||
place: Place { ty: ty, base: base, projections: projections },
|
||||
place: Place { base_ty: base_ty, base: base, projections: projections },
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,10 +137,26 @@ impl<'tcx> Place<'tcx> {
|
||||
/// `x: &*const u32` and the `Place` is `**x`, then the types returned are
|
||||
///`*const u32` then `&*const u32`.
|
||||
crate fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
|
||||
self.projections.iter().rev().filter_map(|proj| {
|
||||
if let ProjectionKind::Deref(deref_ty) = proj.kind { Some(deref_ty) } else { None }
|
||||
self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
|
||||
if ProjectionKind::Deref == proj.kind {
|
||||
Some(self.ty_before_projection(index))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Returns the type of this `Place` after all projections have been applied.
|
||||
pub fn ty(&self) -> Ty<'tcx> {
|
||||
self.projections.last().map_or_else(|| self.base_ty, |proj| proj.ty)
|
||||
}
|
||||
|
||||
// Returns the type of this `Place` immediately before `projection_index`th projection
|
||||
// is applied.
|
||||
crate 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 }
|
||||
}
|
||||
}
|
||||
|
||||
crate trait HirNode {
|
||||
@ -516,8 +535,13 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
) -> PlaceWithHirId<'tcx> {
|
||||
let mut projections = base_place.place.projections;
|
||||
projections.push(Projection { kind: ProjectionKind::Other });
|
||||
let ret = PlaceWithHirId::new(node.hir_id(), ty, base_place.place.base, projections);
|
||||
projections.push(Projection { kind: ProjectionKind::Other, ty: ty });
|
||||
let ret = PlaceWithHirId::new(
|
||||
node.hir_id(),
|
||||
base_place.place.base_ty,
|
||||
base_place.place.base,
|
||||
projections,
|
||||
);
|
||||
debug!("cat_field ret {:?}", ret);
|
||||
ret
|
||||
}
|
||||
@ -552,18 +576,23 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
debug!("cat_deref: base_place={:?}", base_place);
|
||||
|
||||
let base_ty = base_place.place.ty;
|
||||
let deref_ty = match base_ty.builtin_deref(true) {
|
||||
let base_curr_ty = base_place.place.ty();
|
||||
let deref_ty = match base_curr_ty.builtin_deref(true) {
|
||||
Some(mt) => mt.ty,
|
||||
None => {
|
||||
debug!("explicit deref of non-derefable type: {:?}", base_ty);
|
||||
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
let mut projections = base_place.place.projections;
|
||||
projections.push(Projection { kind: ProjectionKind::Deref(base_ty) });
|
||||
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
|
||||
|
||||
let ret = PlaceWithHirId::new(node.hir_id(), deref_ty, base_place.place.base, projections);
|
||||
let ret = PlaceWithHirId::new(
|
||||
node.hir_id(),
|
||||
base_place.place.base_ty,
|
||||
base_place.place.base,
|
||||
projections,
|
||||
);
|
||||
debug!("cat_deref ret {:?}", ret);
|
||||
Ok(ret)
|
||||
}
|
||||
@ -687,7 +716,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
PatKind::Slice(before, ref slice, after) => {
|
||||
let element_ty = match place_with_id.place.ty.builtin_index() {
|
||||
let element_ty = match place_with_id.place.ty().builtin_index() {
|
||||
Some(ty) => ty,
|
||||
None => {
|
||||
debug!("explicit index of non-indexable type {:?}", place_with_id);
|
||||
|
@ -150,7 +150,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
if is_non_trait_box(cmt.place.ty) && !self.is_large_box(cmt.place.ty) {
|
||||
if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
|
||||
self.set.insert(cmt.hir_id);
|
||||
}
|
||||
return;
|
||||
|
Loading…
x
Reference in New Issue
Block a user