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

Make place projections concrete. #60441

Merged
merged 1 commit into from
May 25, 2019
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
76 changes: 32 additions & 44 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -1944,16 +1944,13 @@ 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
Copy link
Member

Choose a reason for hiding this comment

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

Oh, wow, this comment has been wrong for most of MIR's existence, I think?
For reasons, Projection<...> isn't used by MIR borrowck, but ProjectionElem is (as AbstractElem).

I think that's why Projection remained parameterized as well, but I'm not sure.

/// `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,
Hash, RustcEncodable, RustcDecodable, HashStable)]
Expand Down Expand Up @@ -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>>;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
},
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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 { }
Expand Down Expand Up @@ -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::*;

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_mir/borrow_check/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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));
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_mir/borrow_check/places_conflict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/dataflow/drop_flag_effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/dataflow/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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)
}

Expand Down Expand Up @@ -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,
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_mir/transform/uniform_array_move_out.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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}}))));
Expand All @@ -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))
Expand Down