未验证 提交 7942d9a6 编写于 作者: M Manish Goregaokar 提交者: GitHub

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
...@@ -488,7 +488,7 @@ fn check_safety_of_rvalue_destructor_if_necessary( ...@@ -488,7 +488,7 @@ fn check_safety_of_rvalue_destructor_if_necessary(
) { ) {
if let mc::PlaceBase::Rvalue = place_with_id.place.base { if let mc::PlaceBase::Rvalue = place_with_id.place.base {
if place_with_id.place.projections.is_empty() { 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 body_id = self.body_id;
let _ = dropck::check_drop_obligations(self, typ, span, body_id); let _ = dropck::check_drop_obligations(self, typ, span, body_id);
} }
...@@ -640,8 +640,8 @@ fn link_region( ...@@ -640,8 +640,8 @@ fn link_region(
borrow_kind: ty::BorrowKind, borrow_kind: ty::BorrowKind,
borrow_place: &mc::PlaceWithHirId<'tcx>, borrow_place: &mc::PlaceWithHirId<'tcx>,
) { ) {
let origin = infer::DataBorrowed(borrow_place.place.ty, span); let origin = infer::DataBorrowed(borrow_place.place.ty(), span);
self.type_must_outlive(origin, borrow_place.place.ty, borrow_region); self.type_must_outlive(origin, borrow_place.place.ty(), borrow_region);
for pointer_ty in borrow_place.place.deref_tys() { for pointer_ty in borrow_place.place.deref_tys() {
debug!( debug!(
......
...@@ -384,7 +384,7 @@ fn walk_struct_expr( ...@@ -384,7 +384,7 @@ fn walk_struct_expr(
// Select just those fields of the `with` // Select just those fields of the `with`
// expression that will actually be used // 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() => { ty::Adt(adt, substs) if adt.is_struct() => {
// Consume those fields of the with expression that are needed. // Consume those fields of the with expression that are needed.
for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() { for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
...@@ -583,7 +583,7 @@ fn copy_or_move<'a, 'tcx>( ...@@ -583,7 +583,7 @@ fn copy_or_move<'a, 'tcx>(
place_with_id: &PlaceWithHirId<'tcx>, place_with_id: &PlaceWithHirId<'tcx>,
) -> ConsumeMode { ) -> ConsumeMode {
if !mc.type_is_copy_modulo_regions( 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), mc.tcx().hir().span(place_with_id.hir_id),
) { ) {
Move Move
......
...@@ -73,18 +73,21 @@ pub enum PlaceBase { ...@@ -73,18 +73,21 @@ pub enum PlaceBase {
Upvar(ty::UpvarId), Upvar(ty::UpvarId),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum ProjectionKind<'tcx> { pub enum ProjectionKind {
/// A dereference of a pointer, reference or `Box<T>` of the given type /// A dereference of a pointer, reference or `Box<T>` of the given type
Deref(Ty<'tcx>), Deref,
/// An index or a field /// An index or a field
Other, Other,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Projection<'tcx> { pub struct Projection<'tcx> {
// Type after the projection is being applied.
ty: Ty<'tcx>,
/// Defines the type of access /// Defines the type of access
kind: ProjectionKind<'tcx>, kind: ProjectionKind,
} }
/// A `Place` represents how a value is located in memory. /// A `Place` represents how a value is located in memory.
...@@ -92,8 +95,8 @@ pub struct Projection<'tcx> { ...@@ -92,8 +95,8 @@ pub struct Projection<'tcx> {
/// This is an HIR version of `mir::Place` /// This is an HIR version of `mir::Place`
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Place<'tcx> { pub struct Place<'tcx> {
/// The type of the `Place` /// The type of the `PlaceBase`
pub ty: Ty<'tcx>, pub base_ty: Ty<'tcx>,
/// The "outermost" place that holds this value. /// The "outermost" place that holds this value.
pub base: PlaceBase, pub base: PlaceBase,
/// How this place is derived from the base place. /// How this place is derived from the base place.
...@@ -115,13 +118,13 @@ pub struct PlaceWithHirId<'tcx> { ...@@ -115,13 +118,13 @@ pub struct PlaceWithHirId<'tcx> {
impl<'tcx> PlaceWithHirId<'tcx> { impl<'tcx> PlaceWithHirId<'tcx> {
crate fn new( crate fn new(
hir_id: hir::HirId, hir_id: hir::HirId,
ty: Ty<'tcx>, base_ty: Ty<'tcx>,
base: PlaceBase, base: PlaceBase,
projections: Vec<Projection<'tcx>>, projections: Vec<Projection<'tcx>>,
) -> PlaceWithHirId<'tcx> { ) -> PlaceWithHirId<'tcx> {
PlaceWithHirId { PlaceWithHirId {
hir_id: hir_id, 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> { ...@@ -134,10 +137,26 @@ impl<'tcx> Place<'tcx> {
/// `x: &*const u32` and the `Place` is `**x`, then the types returned are /// `x: &*const u32` and the `Place` is `**x`, then the types returned are
///`*const u32` then `&*const u32`. ///`*const u32` then `&*const u32`.
crate fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ { crate fn deref_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
self.projections.iter().rev().filter_map(|proj| { self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| {
if let ProjectionKind::Deref(deref_ty) = proj.kind { Some(deref_ty) } else { None } 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 { crate trait HirNode {
...@@ -516,8 +535,13 @@ fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWit ...@@ -516,8 +535,13 @@ fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWit
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> PlaceWithHirId<'tcx> { ) -> PlaceWithHirId<'tcx> {
let mut projections = base_place.place.projections; let mut projections = base_place.place.projections;
projections.push(Projection { kind: ProjectionKind::Other }); projections.push(Projection { kind: ProjectionKind::Other, ty: ty });
let ret = PlaceWithHirId::new(node.hir_id(), 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_field ret {:?}", ret); debug!("cat_field ret {:?}", ret);
ret ret
} }
...@@ -552,18 +576,23 @@ fn cat_deref( ...@@ -552,18 +576,23 @@ fn cat_deref(
) -> McResult<PlaceWithHirId<'tcx>> { ) -> McResult<PlaceWithHirId<'tcx>> {
debug!("cat_deref: base_place={:?}", base_place); debug!("cat_deref: base_place={:?}", base_place);
let base_ty = base_place.place.ty; let base_curr_ty = base_place.place.ty();
let deref_ty = match base_ty.builtin_deref(true) { let deref_ty = match base_curr_ty.builtin_deref(true) {
Some(mt) => mt.ty, Some(mt) => mt.ty,
None => { None => {
debug!("explicit deref of non-derefable type: {:?}", base_ty); debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
return Err(()); return Err(());
} }
}; };
let mut projections = base_place.place.projections; 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); debug!("cat_deref ret {:?}", ret);
Ok(ret) Ok(ret)
} }
...@@ -687,7 +716,7 @@ fn cat_pattern_<F>( ...@@ -687,7 +716,7 @@ fn cat_pattern_<F>(
} }
PatKind::Slice(before, ref slice, after) => { 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, Some(ty) => ty,
None => { None => {
debug!("explicit index of non-indexable type {:?}", place_with_id); debug!("explicit index of non-indexable type {:?}", place_with_id);
......
...@@ -150,7 +150,7 @@ fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>) { ...@@ -150,7 +150,7 @@ fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>) {
return; 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); self.set.insert(cmt.hir_id);
} }
return; return;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册