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:
parent
46805805ab
commit
123a456a4f
|
@ -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::*;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue