Make place projections concrete.

Once upon a time (commit 9bd35c07c2) there were two kinds of
projection: one for places, and one for constants. It therefore made
sense to share the `Projection` struct for both. Although the different
use-cases used different concrete types, sharing was made possible by
type-parameterisation of `Projection`.

Since then, however, the usage of projections in constants has
disappeared, meaning that (forgetting lifetimes for a moment) the
parameterised type is only every instantiated under one guise. So it may
as well be a concrete type.
This commit is contained in:
Edd Barrett 2019-05-01 15:34:51 +01:00
parent 46805805ab
commit 123a456a4f
10 changed files with 55 additions and 67 deletions

View File

@ -1914,7 +1914,7 @@ pub enum Place<'tcx> {
Base(PlaceBase<'tcx>),
/// projection out of a place (access a field, deref a pointer, etc)
Projection(Box<PlaceProjection<'tcx>>),
Projection(Box<Projection<'tcx>>),
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)]
@ -1944,15 +1944,12 @@ impl_stable_hash_for!(struct Static<'tcx> {
kind
});
/// The `Projection` data structure defines things of the form `B.x`
/// or `*B` or `B[index]`. Note that it is parameterized because it is
/// shared between `Constant` and `Place`. See the aliases
/// `PlaceProjection` etc below.
/// The `Projection` data structure defines things of the form `base.x`, `*b` or `b[index]`.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
Hash, RustcEncodable, RustcDecodable, HashStable)]
pub struct Projection<B, V, T> {
pub base: B,
pub elem: ProjectionElem<V, T>,
pub struct Projection<'tcx> {
pub base: Place<'tcx>,
pub elem: PlaceElem<'tcx>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
@ -1996,10 +1993,6 @@ pub enum ProjectionElem<V, T> {
Downcast(Option<Symbol>, VariantIdx),
}
/// Alias for projections as they appear in places, where the base is a place
/// and the index is a local.
pub type PlaceProjection<'tcx> = Projection<Place<'tcx>, Local, Ty<'tcx>>;
/// Alias for projections as they appear in places, where the base is a place
/// and the index is a local.
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
@ -2045,7 +2038,7 @@ impl<'tcx> Place<'tcx> {
}
pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
Place::Projection(Box::new(PlaceProjection { base: self, elem }))
Place::Projection(Box::new(Projection { base: self, elem }))
}
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
@ -2076,22 +2069,22 @@ impl<'tcx> Place<'tcx> {
}
/// Recursively "iterates" over place components, generating a `PlaceBase` and
/// `PlaceProjections` list and invoking `op` with a `PlaceProjectionsIter`.
/// `Projections` list and invoking `op` with a `ProjectionsIter`.
pub fn iterate<R>(
&self,
op: impl FnOnce(&PlaceBase<'tcx>, PlaceProjectionsIter<'_, 'tcx>) -> R,
op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
) -> R {
self.iterate2(&PlaceProjections::Empty, op)
self.iterate2(&Projections::Empty, op)
}
fn iterate2<R>(
&self,
next: &PlaceProjections<'_, 'tcx>,
op: impl FnOnce(&PlaceBase<'tcx>, PlaceProjectionsIter<'_, 'tcx>) -> R,
next: &Projections<'_, 'tcx>,
op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
) -> R {
match self {
Place::Projection(interior) => interior.base.iterate2(
&PlaceProjections::List {
&Projections::List {
projection: interior,
next,
},
@ -2111,26 +2104,26 @@ impl<'tcx> Place<'tcx> {
/// N.B., this particular impl strategy is not the most obvious. It was
/// chosen because it makes a measurable difference to NLL
/// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot.
pub enum PlaceProjections<'p, 'tcx: 'p> {
pub enum Projections<'p, 'tcx: 'p> {
Empty,
List {
projection: &'p PlaceProjection<'tcx>,
next: &'p PlaceProjections<'p, 'tcx>,
projection: &'p Projection<'tcx>,
next: &'p Projections<'p, 'tcx>,
}
}
impl<'p, 'tcx> PlaceProjections<'p, 'tcx> {
fn iter(&self) -> PlaceProjectionsIter<'_, 'tcx> {
PlaceProjectionsIter { value: self }
impl<'p, 'tcx> Projections<'p, 'tcx> {
fn iter(&self) -> ProjectionsIter<'_, 'tcx> {
ProjectionsIter { value: self }
}
}
impl<'p, 'tcx> IntoIterator for &'p PlaceProjections<'p, 'tcx> {
type Item = &'p PlaceProjection<'tcx>;
type IntoIter = PlaceProjectionsIter<'p, 'tcx>;
impl<'p, 'tcx> IntoIterator for &'p Projections<'p, 'tcx> {
type Item = &'p Projection<'tcx>;
type IntoIter = ProjectionsIter<'p, 'tcx>;
/// Converts a list of `PlaceProjection` components into an iterator;
/// Converts a list of `Projection` components into an iterator;
/// this iterator yields up a never-ending stream of `Option<&Place>`.
/// These begin with the "innermost" projection and then with each
/// projection therefrom. So given a place like `a.b.c` it would
@ -2144,21 +2137,21 @@ impl<'p, 'tcx> IntoIterator for &'p PlaceProjections<'p, 'tcx> {
}
}
/// Iterator over components; see `PlaceProjections::iter` for more
/// Iterator over components; see `Projections::iter` for more
/// information.
///
/// N.B., this is not a *true* Rust iterator -- the code above just
/// manually invokes `next`. This is because we (sometimes) want to
/// keep executing even after `None` has been returned.
pub struct PlaceProjectionsIter<'p, 'tcx: 'p> {
pub value: &'p PlaceProjections<'p, 'tcx>,
pub struct ProjectionsIter<'p, 'tcx: 'p> {
pub value: &'p Projections<'p, 'tcx>,
}
impl<'p, 'tcx> Iterator for PlaceProjectionsIter<'p, 'tcx> {
type Item = &'p PlaceProjection<'tcx>;
impl<'p, 'tcx> Iterator for ProjectionsIter<'p, 'tcx> {
type Item = &'p Projection<'tcx>;
fn next(&mut self) -> Option<Self::Item> {
if let &PlaceProjections::List { projection, next } = self.value {
if let &Projections::List { projection, next } = self.value {
self.value = next;
Some(projection)
} else {
@ -2167,7 +2160,7 @@ impl<'p, 'tcx> Iterator for PlaceProjectionsIter<'p, 'tcx> {
}
}
impl<'p, 'tcx> FusedIterator for PlaceProjectionsIter<'p, 'tcx> {}
impl<'p, 'tcx> FusedIterator for ProjectionsIter<'p, 'tcx> {}
impl<'tcx> Debug for Place<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
@ -2758,7 +2751,7 @@ impl<'tcx> UserTypeProjections {
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
pub struct UserTypeProjection {
pub base: UserTypeAnnotationIndex,
pub projs: Vec<ProjectionElem<(), ()>>,
pub projs: Vec<ProjectionKind>,
}
impl Copy for ProjectionKind { }
@ -3587,12 +3580,7 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
}
}
impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<B, V, T>
where
B: TypeFoldable<'tcx>,
V: TypeFoldable<'tcx>,
T: TypeFoldable<'tcx>,
{
impl<'tcx> TypeFoldable<'tcx> for Projection<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
use crate::mir::ProjectionElem::*;

View File

@ -152,7 +152,7 @@ macro_rules! make_mir_visitor {
}
fn visit_projection(&mut self,
place: & $($mutability)? PlaceProjection<'tcx>,
place: & $($mutability)? Projection<'tcx>,
context: PlaceContext,
location: Location) {
self.super_projection(place, context, location);
@ -689,7 +689,7 @@ macro_rules! make_mir_visitor {
}
fn super_projection(&mut self,
proj: & $($mutability)? PlaceProjection<'tcx>,
proj: & $($mutability)? Projection<'tcx>,
context: PlaceContext,
location: Location) {
let Projection { base, elem } = proj;

View File

@ -2,7 +2,7 @@ use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local,
LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceProjection,
LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, Projection,
ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
};
use rustc::ty::{self, Ty};
@ -619,7 +619,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// union being accessed and the field that was being accessed so we can check the
// second borrowed place for the same union and a access to a different field.
let mut current = first_borrowed_place;
while let Place::Projection(box PlaceProjection { base, elem }) = current {
while let Place::Projection(box Projection { base, elem }) = current {
match elem {
ProjectionElem::Field(field, _) if is_union(base) => {
return Some((base, field));
@ -633,7 +633,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// With the place of a union and a field access into it, we traverse the second
// borrowed place and look for a access to a different field of the same union.
let mut current = second_borrowed_place;
while let Place::Projection(box PlaceProjection { base, elem }) = current {
while let Place::Projection(box Projection { base, elem }) = current {
match elem {
ProjectionElem::Field(field, _) if {
is_union(base) && field != target_field && base == target_base
@ -1495,7 +1495,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Place::Base(PlaceBase::Static(_)) => {
StorageDeadOrDrop::LocalStorageDead
}
Place::Projection(box PlaceProjection { base, elem }) => {
Place::Projection(box Projection { base, elem }) => {
let base_access = self.classify_drop_access_kind(base);
match elem {
ProjectionElem::Deref => match base_access {

View File

@ -352,7 +352,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
..
} => {
let try_remove_deref = match move_from {
Place::Projection(box PlaceProjection {
Place::Projection(box Projection {
elem: ProjectionElem::Deref,
..
}) => true,

View File

@ -2370,7 +2370,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
"add_reborrow_constraint({:?}, {:?}, {:?})",
location, borrow_region, borrowed_place
);
while let Place::Projection(box PlaceProjection { base, elem }) = borrowed_place {
while let Place::Projection(box Projection { base, elem }) = borrowed_place {
debug!("add_reborrow_constraint - iteration {:?}", borrowed_place);
match *elem {

View File

@ -3,7 +3,7 @@ use crate::borrow_check::Overlap;
use crate::borrow_check::{Deep, Shallow, AccessDepth};
use rustc::hir;
use rustc::mir::{
BorrowKind, Mir, Place, PlaceBase, PlaceProjection, ProjectionElem, PlaceProjectionsIter,
BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem, ProjectionsIter,
StaticKind
};
use rustc::ty::{self, TyCtxt};
@ -86,9 +86,9 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
fn place_components_conflict<'gcx, 'tcx>(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
borrow_projections: (&PlaceBase<'tcx>, PlaceProjectionsIter<'_, 'tcx>),
borrow_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>),
borrow_kind: BorrowKind,
access_projections: (&PlaceBase<'tcx>, PlaceProjectionsIter<'_, 'tcx>),
access_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>),
access: AccessDepth,
bias: PlaceConflictBias,
) -> bool {
@ -368,8 +368,8 @@ fn place_base_conflict<'a, 'gcx: 'tcx, 'tcx>(
fn place_projection_conflict<'a, 'gcx: 'tcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
pi1: &PlaceProjection<'tcx>,
pi2: &PlaceProjection<'tcx>,
pi1: &Projection<'tcx>,
pi2: &Projection<'tcx>,
bias: PlaceConflictBias,
) -> Overlap {
match (&pi1.elem, &pi2.elem) {

View File

@ -10,7 +10,7 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
path: MovePathIndex,
mut cond: F)
-> Option<MovePathIndex>
where F: FnMut(&mir::PlaceProjection<'tcx>) -> bool
where F: FnMut(&mir::Projection<'tcx>) -> bool
{
let mut next_child = move_data.move_paths[path].first_child;
while let Some(child_index) = next_child {

View File

@ -114,7 +114,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
fn move_path_for_projection(&mut self,
place: &Place<'tcx>,
proj: &PlaceProjection<'tcx>)
proj: &Projection<'tcx>)
-> Result<MovePathIndex, MoveError<'tcx>>
{
let base = self.move_path_for(&proj.base)?;

View File

@ -161,7 +161,7 @@ trait Qualif {
fn in_projection_structurally(
cx: &ConstCx<'_, 'tcx>,
proj: &PlaceProjection<'tcx>,
proj: &Projection<'tcx>,
) -> bool {
let base_qualif = Self::in_place(cx, &proj.base);
let qualif = base_qualif && Self::mask_for_ty(
@ -181,7 +181,7 @@ trait Qualif {
}
}
fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &PlaceProjection<'tcx>) -> bool {
fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &Projection<'tcx>) -> bool {
Self::in_projection_structurally(cx, proj)
}
@ -387,7 +387,7 @@ impl Qualif for IsNotPromotable {
}
}
fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &PlaceProjection<'tcx>) -> bool {
fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &Projection<'tcx>) -> bool {
match proj.elem {
ProjectionElem::Deref |
ProjectionElem::Downcast(..) => return true,

View File

@ -89,7 +89,7 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
fn uniform(&mut self,
location: Location,
dst_place: &Place<'tcx>,
proj: &PlaceProjection<'tcx>,
proj: &Projection<'tcx>,
item_ty: &'tcx ty::TyS<'tcx>,
size: u32) {
match proj.elem {
@ -103,7 +103,7 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
Place::Base(PlaceBase::Local(temp)),
Rvalue::Use(
Operand::Move(
Place::Projection(box PlaceProjection{
Place::Projection(box Projection{
base: proj.base.clone(),
elem: ProjectionElem::ConstantIndex{
offset: i,
@ -133,7 +133,7 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
dst_place.clone(),
Rvalue::Use(
Operand::Move(
Place::Projection(box PlaceProjection{
Place::Projection(box Projection{
base: proj.base.clone(),
elem: ProjectionElem::ConstantIndex{
offset: size - offset,
@ -246,7 +246,7 @@ impl RestoreSubsliceArrayMoveOut {
dst_place.clone(),
Rvalue::Use(
Operand::Move(
Place::Projection(box PlaceProjection{
Place::Projection(box Projection{
base: opt_src_place.unwrap().clone(),
elem: ProjectionElem::Subslice{
from: min, to: size - max - 1}}))));
@ -261,7 +261,7 @@ impl RestoreSubsliceArrayMoveOut {
let statement = &block.statements[location.statement_index];
if let StatementKind::Assign(
Place::Base(PlaceBase::Local(_)),
box Rvalue::Use(Operand::Move(Place::Projection(box PlaceProjection{
box Rvalue::Use(Operand::Move(Place::Projection(box Projection{
ref base, elem: ProjectionElem::ConstantIndex{
offset, min_length: _, from_end: false}})))) = statement.kind {
return Some((offset, base))