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

Remove adt_def from projections and downcasts in MIR #59514

Merged
merged 2 commits into from
Apr 3, 2019
Merged
Changes from 1 commit
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
116 changes: 42 additions & 74 deletions src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
@@ -4,21 +4,17 @@
*/

use crate::mir::*;
use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{self, AdtDef, Ty, TyCtxt};
use crate::ty::subst::Subst;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::layout::VariantIdx;
use crate::hir;
use crate::ty::util::IntTypeExt;

#[derive(Copy, Clone, Debug)]
pub enum PlaceTy<'tcx> {
/// Normal type.
Ty { ty: Ty<'tcx> },

/// Downcast to a particular variant of an enum.
Downcast { adt_def: &'tcx AdtDef,
substs: SubstsRef<'tcx>,
variant_index: VariantIdx },
pub struct PlaceTy<'tcx> {
pub ty: Ty<'tcx>,
/// Downcast to a particular variant of an enum, if included.
pub variant_index: Option<VariantIdx>,
}

static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
@@ -27,16 +23,7 @@ static_assert!(PLACE_TY_IS_3_PTRS_LARGE:

impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
PlaceTy::Ty { ty }
}

pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
match *self {
PlaceTy::Ty { ty } =>
ty,
PlaceTy::Downcast { adt_def, substs, variant_index: _ } =>
tcx.mk_adt(adt_def, substs),
}
PlaceTy { ty, variant_index: None }
}

/// `place_ty.field_ty(tcx, f)` computes the type at a given field
@@ -48,21 +35,20 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
/// Note that the resulting type has not been normalized.
pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
{
// Pass `0` here so it can be used as a "default" variant_index in first arm below
let answer = match (self, VariantIdx::new(0)) {
(PlaceTy::Ty {
ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) |
(PlaceTy::Downcast { adt_def, substs, variant_index }, _) => {
let variant_def = &adt_def.variants[variant_index];
let answer = match self.ty.sty {
ty::TyKind::Adt(adt_def, substs) => {
let variant_def = match self.variant_index {
None => adt_def.non_enum_variant(),
Some(variant_index) => {
assert!(adt_def.is_enum());
&adt_def.variants[variant_index]
}
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is subtly incomplete, but pre-existing.
The non-downcast case should use .non_enum_variant() to get the variant, while downcasts should assert the ADT is an enum.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

let field_def = &variant_def.fields[f.index()];
field_def.ty(tcx, substs)
}
(PlaceTy::Ty { ty }, _) => {
match ty.sty {
ty::Tuple(ref tys) => tys[f.index()],
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
}
}
ty::Tuple(ref tys) => tys[f.index()],
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
};
debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
answer
@@ -94,61 +80,43 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
{
let answer = match *elem {
ProjectionElem::Deref => {
let ty = self.to_ty(tcx)
let ty = self.ty
.builtin_deref(true)
.unwrap_or_else(|| {
bug!("deref projection of non-dereferencable ty {:?}", self)
})
.ty;
PlaceTy::Ty {
ty,
}
PlaceTy::from_ty(ty)
}
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
PlaceTy::Ty {
ty: self.to_ty(tcx).builtin_index().unwrap()
},
PlaceTy::from_ty(self.ty.builtin_index().unwrap()),
ProjectionElem::Subslice { from, to } => {
let ty = self.to_ty(tcx);
PlaceTy::Ty {
ty: match ty.sty {
ty::Array(inner, size) => {
let size = size.unwrap_usize(tcx);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(inner, len)
}
ty::Slice(..) => ty,
_ => {
bug!("cannot subslice non-array type: `{:?}`", self)
}
}
}
}
ProjectionElem::Downcast(_name, index) =>
match self.to_ty(tcx).sty {
ty::Adt(adt_def, substs) => {
assert!(adt_def.is_enum());
assert!(index.as_usize() < adt_def.variants.len());
PlaceTy::Downcast { adt_def,
substs,
variant_index: index }
PlaceTy::from_ty(match self.ty.sty {
ty::Array(inner, size) => {
let size = size.unwrap_usize(tcx);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(inner, len)
}
ty::Slice(..) => self.ty,
_ => {
bug!("cannot downcast non-ADT type: `{:?}`", self)
bug!("cannot subslice non-array type: `{:?}`", self)
}
},
})
}
ProjectionElem::Downcast(_name, index) =>
PlaceTy { ty: self.ty, variant_index: Some(index) },
ProjectionElem::Field(ref f, ref fty) =>
PlaceTy::Ty { ty: handle_field(&self, f, fty) },
PlaceTy::from_ty(handle_field(&self, f, fty)),
};
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
answer
}
}

EnumTypeFoldableImpl! {
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> {
(PlaceTy::Ty) { ty },
(PlaceTy::Downcast) { adt_def, substs, variant_index },
ty,
variant_index,
}
}

@@ -158,9 +126,9 @@ impl<'tcx> Place<'tcx> {
{
match *self {
Place::Base(PlaceBase::Local(index)) =>
PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
PlaceTy::from_ty(local_decls.local_decls()[index].ty),
Place::Base(PlaceBase::Static(ref data)) =>
PlaceTy::Ty { ty: data.ty },
PlaceTy::from_ty(data.ty),
Place::Projection(ref proj) =>
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
}
@@ -185,7 +153,7 @@ impl<'tcx> Place<'tcx> {
match place {
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Field(field, _ty) => {
let base_ty = proj.base.ty(mir, *tcx).to_ty(*tcx);
let base_ty = proj.base.ty(mir, *tcx).ty;

if (base_ty.is_closure() || base_ty.is_generator()) &&
(!by_ref || mir.upvar_decls[field.index()].by_ref)
@@ -217,7 +185,7 @@ impl<'tcx> Rvalue<'tcx> {
tcx.mk_array(operand.ty(local_decls, tcx), count)
}
Rvalue::Ref(reg, bk, ref place) => {
let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
let place_ty = place.ty(local_decls, tcx).ty;
tcx.mk_ref(reg,
ty::TypeAndMut {
ty: place_ty,
@@ -243,7 +211,7 @@ impl<'tcx> Rvalue<'tcx> {
operand.ty(local_decls, tcx)
}
Rvalue::Discriminant(ref place) => {
let ty = place.ty(local_decls, tcx).to_ty(tcx);
let ty = place.ty(local_decls, tcx).ty;
if let ty::Adt(adt_def, _) = ty.sty {
adt_def.repr.discr_type().to_ty(tcx)
} else {
@@ -292,7 +260,7 @@ impl<'tcx> Operand<'tcx> {
{
match self {
&Operand::Copy(ref l) |
&Operand::Move(ref l) => l.ty(local_decls, tcx).to_ty(tcx),
&Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
&Operand::Constant(ref c) => c.ty,
}
}
6 changes: 3 additions & 3 deletions src/librustc_codegen_ssa/mir/analyze.rs
Original file line number Diff line number Diff line change
@@ -172,14 +172,14 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
// ZSTs don't require any actual memory access.
let elem_ty = base_ty
.projection_ty(cx.tcx(), &proj.elem)
.to_ty(cx.tcx());
.ty;
let elem_ty = self.fx.monomorphize(&elem_ty);
if cx.layout_of(elem_ty).is_zst() {
return;
}

if let mir::ProjectionElem::Field(..) = proj.elem {
let layout = cx.layout_of(base_ty.to_ty(cx.tcx()));
let layout = cx.layout_of(base_ty.ty);
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
// Recurse with the same context, instead of `Projection`,
// potentially stopping at non-operand projections,
@@ -247,7 +247,7 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
let ty = mir::Place::Base(mir::PlaceBase::Local(local)).ty(self.fx.mir,
self.fx.cx.tcx());
let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx()));
let ty = self.fx.monomorphize(&ty.ty);

// Only need the place if we're actually dropping it.
if self.fx.cx.type_needs_drop(ty) {
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
@@ -301,7 +301,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
target: mir::BasicBlock,
unwind: Option<mir::BasicBlock>,
) {
let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
let ty = location.ty(self.mir, bx.tcx()).ty;
let ty = self.monomorphize(&ty);
let drop_fn = monomorphize::resolve_drop_in_place(bx.tcx(), ty);

6 changes: 3 additions & 3 deletions src/librustc_codegen_ssa/mir/place.rs
Original file line number Diff line number Diff line change
@@ -494,8 +494,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::ProjectionElem::Subslice { from, to } => {
let mut subslice = cg_base.project_index(bx,
bx.cx().const_usize(from as u64));
let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty }
.projection_ty(tcx, &projection.elem).to_ty(tcx);
let projected_ty = PlaceTy::from_ty(cg_base.layout.ty)
.projection_ty(tcx, &projection.elem).ty;
subslice.layout = bx.cx().layout_of(self.monomorphize(&projected_ty));

if subslice.layout.is_unsized() {
@@ -523,6 +523,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn monomorphized_place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
let tcx = self.cx.tcx();
let place_ty = place.ty(self.mir, tcx);
self.monomorphize(&place_ty.to_ty(tcx))
self.monomorphize(&place_ty.ty)
}
}
15 changes: 7 additions & 8 deletions src/librustc_mir/borrow_check/error_reporting.rs
Original file line number Diff line number Diff line change
@@ -202,7 +202,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
);
}

let ty = used_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
let ty = used_place.ty(self.mir, self.infcx.tcx).ty;
let needs_note = match ty.sty {
ty::Closure(id, _) => {
let tables = self.infcx.tcx.typeck_tables_of(id);
@@ -217,7 +217,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let mpi = self.move_data.moves[move_out_indices[0]].path;
let place = &self.move_data.move_paths[mpi].place;

let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
let ty = place.ty(self.mir, self.infcx.tcx).ty;
let opt_name = self.describe_place_with_options(place, IncludingDowncast(true));
let note_msg = match opt_name {
Some(ref name) => format!("`{}`", name),
@@ -601,8 +601,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// Define a small closure that we can use to check if the type of a place
// is a union.
let is_union = |place: &Place<'tcx>| -> bool {
place.ty(self.mir, self.infcx.tcx)
.to_ty(self.infcx.tcx)
place.ty(self.mir, self.infcx.tcx).ty
.ty_adt_def()
.map(|adt| adt.is_union())
.unwrap_or(false)
@@ -651,7 +650,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {

// Also compute the name of the union type, eg. `Foo` so we
// can add a helpful note with it.
let ty = base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
let ty = base.ty(self.mir, self.infcx.tcx).ty;

return Some((desc_base, desc_first, desc_second, ty.to_string()));
},
@@ -1777,7 +1776,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Deref => self.describe_field(&proj.base, field),
ProjectionElem::Downcast(_, variant_index) => {
let base_ty = base.ty(self.mir, self.infcx.tcx).to_ty();
let base_ty = base.ty(self.mir, self.infcx.tcx).ty;
self.describe_field_from_ty(&base_ty, field, Some(variant_index))
}
ProjectionElem::Field(_, field_type) => {
@@ -1878,15 +1877,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
StorageDeadOrDrop::LocalStorageDead
| StorageDeadOrDrop::BoxedStorageDead => {
assert!(
base.ty(self.mir, tcx).to_ty(tcx).is_box(),
base.ty(self.mir, tcx).ty.is_box(),
"Drop of value behind a reference or raw pointer"
);
StorageDeadOrDrop::BoxedStorageDead
}
StorageDeadOrDrop::Destructor(_) => base_access,
},
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
let base_ty = base.ty(self.mir, tcx).ty;
match base_ty.sty {
ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor
9 changes: 4 additions & 5 deletions src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
@@ -616,8 +616,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
let drop_place_ty = drop_place.ty(self.mir, self.infcx.tcx);

// Erase the regions.
let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty)
.to_ty(self.infcx.tcx);
let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty;

// "Lift" into the gcx -- once regions are erased, this type should be in the
// global arenas; this "lift" operation basically just asserts that is true, but
@@ -1641,7 +1640,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// assigning to `P.f` requires `P` itself
// be already initialized
let tcx = self.infcx.tcx;
match base.ty(self.mir, tcx).to_ty(tcx).sty {
match base.ty(self.mir, tcx).ty.sty {
ty::Adt(def, _) if def.has_dtor(tcx) => {
self.check_if_path_or_subpath_is_moved(
context, InitializationRequiringAction::Assignment,
@@ -1746,7 +1745,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// no move out from an earlier location) then this is an attempt at initialization
// of the union - we should error in that case.
let tcx = this.infcx.tcx;
if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).to_ty(tcx).sty {
if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).ty.sty {
if def.is_union() {
if this.move_data.path_map[mpi].iter().any(|moi| {
this.move_data.moves[*moi].source.is_predecessor_of(
@@ -2007,7 +2006,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref => {
let base_ty = proj.base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
let base_ty = proj.base.ty(self.mir, self.infcx.tcx).ty;

// Check the kind of deref to decide
match base_ty.sty {
8 changes: 4 additions & 4 deletions src/librustc_mir/borrow_check/move_errors.rs
Original file line number Diff line number Diff line change
@@ -266,7 +266,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
// Inspect the type of the content behind the
// borrow to provide feedback about why this
// was a move rather than a copy.
let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
let ty = place.ty(self.mir, self.infcx.tcx).ty;
let is_upvar_field_projection =
self.prefixes(&original_path, PrefixSet::All)
.any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
@@ -530,7 +530,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
// We're only interested in assignments (in particular, where the
// assignment came from - was it an `Rc` or `Arc`?).
if let StatementKind::Assign(_, box Rvalue::Ref(_, _, source)) = &stmt.kind {
let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
let ty = source.ty(self.mir, self.infcx.tcx).ty;
let ty = match ty.sty {
ty::TyKind::Ref(_, ty, _) => ty,
_ => ty,
@@ -555,7 +555,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
_ => continue,
};

let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
let ty = source.ty(self.mir, self.infcx.tcx).ty;
let ty = match ty.sty {
ty::TyKind::Ref(_, ty, _) => ty,
_ => ty,
@@ -581,7 +581,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
base,
elem: ProjectionElem::Deref,
}) = place {
if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() {
if base.ty(self.mir, self.infcx.tcx).ty.is_unsafe_ptr() {
return BorrowedContentSource::DerefRawPointer;
}
}
Loading