Auto merge of #60441 - vext01:try-to-kill-projection-params, r=oli-obk

Make place projections concrete.

**I'm not sure if we want this. I'm raising the PR  for discussion**

Whilst doing some work on our Rust fork, I noticed the following:

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. Right?

What do people think? This is entirely untested, although it does check.

If we *don't* want this, then we should at least update the incorrect comment against `Projection`.

Thanks
This commit is contained in:
bors 2019-05-25 01:20:07 +00:00
commit 5245803120
10 changed files with 55 additions and 67 deletions

View file

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

View file

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

View file

@ -2,7 +2,7 @@ use rustc::hir;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::mir::{ use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local, 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, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
}; };
use rustc::ty::{self, Ty}; 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 // 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. // second borrowed place for the same union and a access to a different field.
let mut current = first_borrowed_place; 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 { match elem {
ProjectionElem::Field(field, _) if is_union(base) => { ProjectionElem::Field(field, _) if is_union(base) => {
return Some((base, field)); 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 // 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. // borrowed place and look for a access to a different field of the same union.
let mut current = second_borrowed_place; 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 { match elem {
ProjectionElem::Field(field, _) if { ProjectionElem::Field(field, _) if {
is_union(base) && field != target_field && base == target_base 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(_)) => { Place::Base(PlaceBase::Static(_)) => {
StorageDeadOrDrop::LocalStorageDead StorageDeadOrDrop::LocalStorageDead
} }
Place::Projection(box PlaceProjection { base, elem }) => { Place::Projection(box Projection { base, elem }) => {
let base_access = self.classify_drop_access_kind(base); let base_access = self.classify_drop_access_kind(base);
match elem { match elem {
ProjectionElem::Deref => match base_access { 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 { let try_remove_deref = match move_from {
Place::Projection(box PlaceProjection { Place::Projection(box Projection {
elem: ProjectionElem::Deref, elem: ProjectionElem::Deref,
.. ..
}) => true, }) => true,

View file

@ -2370,7 +2370,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
"add_reborrow_constraint({:?}, {:?}, {:?})", "add_reborrow_constraint({:?}, {:?}, {:?})",
location, borrow_region, borrowed_place 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); debug!("add_reborrow_constraint - iteration {:?}", borrowed_place);
match *elem { match *elem {

View file

@ -3,7 +3,7 @@ use crate::borrow_check::Overlap;
use crate::borrow_check::{Deep, Shallow, AccessDepth}; use crate::borrow_check::{Deep, Shallow, AccessDepth};
use rustc::hir; use rustc::hir;
use rustc::mir::{ use rustc::mir::{
BorrowKind, Mir, Place, PlaceBase, PlaceProjection, ProjectionElem, PlaceProjectionsIter, BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem, ProjectionsIter,
StaticKind StaticKind
}; };
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
@ -86,9 +86,9 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
fn place_components_conflict<'gcx, 'tcx>( fn place_components_conflict<'gcx, 'tcx>(
tcx: TyCtxt<'_, 'gcx, 'tcx>, tcx: TyCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>, mir: &Mir<'tcx>,
borrow_projections: (&PlaceBase<'tcx>, PlaceProjectionsIter<'_, 'tcx>), borrow_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>),
borrow_kind: BorrowKind, borrow_kind: BorrowKind,
access_projections: (&PlaceBase<'tcx>, PlaceProjectionsIter<'_, 'tcx>), access_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>),
access: AccessDepth, access: AccessDepth,
bias: PlaceConflictBias, bias: PlaceConflictBias,
) -> bool { ) -> bool {
@ -368,8 +368,8 @@ fn place_base_conflict<'a, 'gcx: 'tcx, 'tcx>(
fn place_projection_conflict<'a, 'gcx: 'tcx, 'tcx>( fn place_projection_conflict<'a, 'gcx: 'tcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>, mir: &Mir<'tcx>,
pi1: &PlaceProjection<'tcx>, pi1: &Projection<'tcx>,
pi2: &PlaceProjection<'tcx>, pi2: &Projection<'tcx>,
bias: PlaceConflictBias, bias: PlaceConflictBias,
) -> Overlap { ) -> Overlap {
match (&pi1.elem, &pi2.elem) { 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, path: MovePathIndex,
mut cond: F) mut cond: F)
-> Option<MovePathIndex> -> 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; let mut next_child = move_data.move_paths[path].first_child;
while let Some(child_index) = next_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, fn move_path_for_projection(&mut self,
place: &Place<'tcx>, place: &Place<'tcx>,
proj: &PlaceProjection<'tcx>) proj: &Projection<'tcx>)
-> Result<MovePathIndex, MoveError<'tcx>> -> Result<MovePathIndex, MoveError<'tcx>>
{ {
let base = self.move_path_for(&proj.base)?; let base = self.move_path_for(&proj.base)?;

View file

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

View file

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