Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typeck: adding type information to projection #73870

Merged
merged 1 commit into from
Jul 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/librustc_typeck/check/regionck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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!(
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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
Expand Down
67 changes: 48 additions & 19 deletions src/librustc_typeck/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,27 +73,30 @@ 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.
///
/// 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.
Expand All @@ -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 },
}
}
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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) });

let ret = PlaceWithHirId::new(node.hir_id(), deref_ty, base_place.place.base, projections);
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });

let ret = PlaceWithHirId::new(
node.hir_id(),
base_place.place.base_ty,
base_place.place.base,
projections,
);
debug!("cat_deref ret {:?}", ret);
Ok(ret)
}
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/escape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down