-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[nll] change how MIR represents places #53247
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
Closed
Closed
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
357bc2c
Introduce new Place in librustc/mir
csmoe 34329c0
Intern Place elems
csmoe bd9f156
Add split_projection/base_place method
csmoe 85a87a1
Try read Place
csmoe a5c428b
Replace with new Place in mir/borrowck
csmoe 6002649
Clean up old Place in rustc_mir
csmoe b1dbe6f
Intern PlaceElem with iterator
csmoe c5a7e57
Remove Projection and impl stablehash for Place with macro
csmoe e684ea3
Rewrite places_conflict
csmoe 091802d
Rewrite recurseive place traversal to iteration
csmoe c1fff48
Port new Place into llvm codegen
csmoe 56773a9
refactor `PlaceTy::base_ty` into a method on `PlaceBase`
nikomatsakis 36b5cac
fix the whitespace after `elems}`
nikomatsakis 2cd7680
rewrite `builder` so that it terminates
nikomatsakis ec40255
Rewrite place workflow in rustc_mir/interpret
csmoe 7b65566
Rewrite place workflow in rustc_mir/borrow_check
csmoe a6520ec
Rewrite place workflow in rustc_mir/dataflow
csmoe fea2e88
Rewrite place workflow in rustc_mir/transform
csmoe 244fbb4
Rewrite place workflow in rustc_codegen_llvm
csmoe 73e86a2
Rewrite place workflow in rustc_mir/build
csmoe 5aae53e
Introduce has_no_projection
csmoe 9ec03b3
Rewrite place workflow in rustc_passes
csmoe 2af0dd0
Rewrite place workflow in rustc_mir/util
csmoe 6045a8a
move `PlaceContext::Copy` check later, once type is fully computed
nikomatsakis e912a26
Trip unneeded has_no_projection checking
csmoe 13a9c20
Separate inner closure to fn
csmoe d5095f6
Fix mutability capture from place
csmoe 6f8aa3d
mutability_errors: rustfmt
csmoe 7da7205
returns immediately on references error
csmoe c47b2a9
guarantee working no projection place when reporting mutability error
csmoe 8616672
working on on projection place when visit_assign
csmoe ba7feb1
guarantee has_no_projection when visit_rvalue
csmoe 552a935
guarantee has_no_projection in uniform_array_moveout
csmoe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ use mir::interpret::{EvalErrorKind, Scalar, Value, ScalarMaybeUndef}; | |
use mir::visit::MirVisitable; | ||
use rustc_apfloat::ieee::{Double, Single}; | ||
use rustc_apfloat::Float; | ||
use rustc_data_structures::accumulate_vec::AccumulateVec; | ||
use rustc_data_structures::graph::dominators::{dominators, Dominators}; | ||
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; | ||
use rustc_data_structures::indexed_vec::{Idx, IndexVec}; | ||
|
@@ -39,7 +40,7 @@ use syntax::symbol::InternedString; | |
use syntax_pos::{Span, DUMMY_SP}; | ||
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; | ||
use ty::subst::{Subst, Substs}; | ||
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt}; | ||
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Slice, Ty, TyCtxt}; | ||
use util::ppaux; | ||
|
||
pub use mir::interpret::AssertMessage; | ||
|
@@ -1693,8 +1694,16 @@ impl<'tcx> Debug for Statement<'tcx> { | |
|
||
/// A path to a value; something that can be evaluated without | ||
/// changing or disturbing program state. | ||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] | ||
pub struct Place<'tcx> { | ||
pub base: PlaceBase<'tcx>, | ||
pub elems: &'tcx Slice<PlaceElem<'tcx>>, | ||
} | ||
|
||
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<PlaceElem<'tcx>> {} | ||
|
||
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] | ||
pub enum Place<'tcx> { | ||
pub enum PlaceBase<'tcx> { | ||
/// local variable | ||
Local(Local), | ||
|
||
|
@@ -1703,9 +1712,6 @@ pub enum Place<'tcx> { | |
|
||
/// Constant code promoted to an injected static | ||
Promoted(Box<(Promoted, Ty<'tcx>)>), | ||
|
||
/// projection out of a place (access a field, deref a pointer, etc) | ||
Projection(Box<PlaceProjection<'tcx>>), | ||
} | ||
|
||
/// The def-id of a static, along with its normalized type (which is | ||
|
@@ -1721,17 +1727,7 @@ impl_stable_hash_for!(struct Static<'tcx> { | |
ty | ||
}); | ||
|
||
/// 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. | ||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] | ||
pub struct Projection<'tcx, B, V, T> { | ||
pub base: B, | ||
pub elem: ProjectionElem<'tcx, V, T>, | ||
} | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] | ||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] | ||
pub enum ProjectionElem<'tcx, V, T> { | ||
Deref, | ||
Field(Field, T), | ||
|
@@ -1769,41 +1765,108 @@ pub enum ProjectionElem<'tcx, V, T> { | |
Downcast(&'tcx AdtDef, usize), | ||
} | ||
|
||
/// 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<'tcx, 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<'tcx, Local, Ty<'tcx>>; | ||
|
||
newtype_index!(Field { DEBUG_FORMAT = "field[{}]" }); | ||
|
||
impl<'tcx> Place<'tcx> { | ||
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { | ||
self.elem(ProjectionElem::Field(f, ty)) | ||
impl<'a, 'tcx> Place<'tcx> { | ||
// projection lives in the last elem. | ||
pub fn projection(&self) -> Option<&PlaceElem> { | ||
self.elems.last() | ||
} | ||
|
||
pub fn field( | ||
self, | ||
tcx: TyCtxt<'_, '_, 'tcx>, | ||
f: Field, | ||
ty: Ty<'tcx>, | ||
) -> Self { | ||
self.elem(tcx, ProjectionElem::Field(f, ty)) | ||
} | ||
|
||
pub fn deref(self, tcx: TyCtxt<'_, '_, 'tcx>) -> Self { | ||
self.elem(tcx, ProjectionElem::Deref) | ||
} | ||
|
||
pub fn downcast( | ||
self, | ||
tcx: TyCtxt<'_, '_, 'tcx>, | ||
adt_def: &'tcx AdtDef, | ||
variant_index: usize, | ||
) -> Self { | ||
self.elem(tcx, ProjectionElem::Downcast(adt_def, variant_index)) | ||
} | ||
|
||
pub fn index(self, tcx: TyCtxt<'_, '_, 'tcx>, index: Local) -> Self { | ||
self.elem(tcx, ProjectionElem::Index(index)) | ||
} | ||
|
||
pub fn constant_index( | ||
self, | ||
tcx: TyCtxt<'_, '_, 'tcx>, | ||
offset: u32, | ||
min_length: u32, | ||
from_end: bool, | ||
) -> Self { | ||
self.elem(tcx, ProjectionElem::ConstantIndex { | ||
offset, min_length, from_end, | ||
}) | ||
} | ||
|
||
pub fn subslice( | ||
self, | ||
tcx: TyCtxt<'_, '_, 'tcx>, | ||
from: u32, | ||
to: u32, | ||
) -> Self { | ||
self.elem(tcx, ProjectionElem::Subslice { | ||
from, to, | ||
}) | ||
} | ||
|
||
pub fn deref(self) -> Place<'tcx> { | ||
self.elem(ProjectionElem::Deref) | ||
pub fn local(local: Local) -> Self { | ||
Place { | ||
base: PlaceBase::Local(local), | ||
elems: Slice::empty(), | ||
} | ||
} | ||
|
||
pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> { | ||
self.elem(ProjectionElem::Downcast(adt_def, variant_index)) | ||
pub fn static_(static_: Static<'tcx>) -> Self { | ||
Place { | ||
base: PlaceBase::Static(box static_), | ||
elems: Slice::empty(), | ||
} | ||
} | ||
|
||
pub fn index(self, index: Local) -> Place<'tcx> { | ||
self.elem(ProjectionElem::Index(index)) | ||
pub fn promoted( | ||
promoted: Promoted, | ||
ty: Ty<'tcx>, | ||
) -> Self { | ||
Place { | ||
base: PlaceBase::Promoted(box (promoted, ty)), | ||
elems: Slice::empty(), | ||
} | ||
} | ||
|
||
pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> { | ||
Place::Projection(Box::new(PlaceProjection { base: self, elem })) | ||
fn elem( | ||
self, | ||
tcx: TyCtxt<'_, '_, 'tcx>, | ||
elem: PlaceElem<'tcx>, | ||
) -> Self { | ||
Place { | ||
base: self.base, | ||
elems: tcx.mk_place_elems( | ||
self.elems.iter().cloned().chain(iter::once(elem)) | ||
), | ||
} | ||
} | ||
} | ||
|
||
impl<'tcx> Debug for Place<'tcx> { | ||
impl<'tcx> Debug for PlaceBase<'tcx> { | ||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { | ||
use self::Place::*; | ||
use self::PlaceBase::*; | ||
|
||
match *self { | ||
Local(id) => write!(fmt, "{:?}", id), | ||
|
@@ -1814,35 +1877,6 @@ impl<'tcx> Debug for Place<'tcx> { | |
ty | ||
), | ||
Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1), | ||
Projection(ref data) => match data.elem { | ||
ProjectionElem::Downcast(ref adt_def, index) => { | ||
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name) | ||
} | ||
ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base), | ||
ProjectionElem::Field(field, ty) => { | ||
write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty) | ||
} | ||
ProjectionElem::Index(ref index) => write!(fmt, "{:?}[{:?}]", data.base, index), | ||
ProjectionElem::ConstantIndex { | ||
offset, | ||
min_length, | ||
from_end: false, | ||
} => write!(fmt, "{:?}[{:?} of {:?}]", data.base, offset, min_length), | ||
ProjectionElem::ConstantIndex { | ||
offset, | ||
min_length, | ||
from_end: true, | ||
} => write!(fmt, "{:?}[-{:?} of {:?}]", data.base, offset, min_length), | ||
ProjectionElem::Subslice { from, to } if to == 0 => { | ||
write!(fmt, "{:?}[{:?}:]", data.base, from) | ||
} | ||
ProjectionElem::Subslice { from, to } if from == 0 => { | ||
write!(fmt, "{:?}[:-{:?}]", data.base, to) | ||
} | ||
ProjectionElem::Subslice { from, to } => { | ||
write!(fmt, "{:?}[{:?}:-{:?}]", data.base, from, to) | ||
} | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to move this in a custom |
||
} | ||
} | ||
} | ||
|
@@ -2760,18 +2794,36 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { | |
|
||
impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { | ||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { | ||
match self { | ||
&Place::Projection(ref p) => Place::Projection(p.fold_with(folder)), | ||
_ => self.clone(), | ||
Place { | ||
base: self.base.fold_with(folder), | ||
elems: self.elems.fold_with(folder), | ||
csmoe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { | ||
if let &Place::Projection(ref p) = self { | ||
p.visit_with(visitor) | ||
} else { | ||
false | ||
} | ||
self.base.visit_with(visitor) || | ||
self.elems.visit_with(visitor) | ||
} | ||
} | ||
|
||
impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> { | ||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { | ||
self.clone() | ||
} | ||
|
||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool { | ||
false | ||
} | ||
} | ||
|
||
impl<'tcx> TypeFoldable<'tcx> for &'tcx Slice<PlaceElem<'tcx>> { | ||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { | ||
let v = self.iter().map(|p| p.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>(); | ||
folder.tcx().intern_place_elems(&v) | ||
} | ||
|
||
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool { | ||
self.iter().any(|p| p.visit_with(visitor)) | ||
} | ||
} | ||
|
||
|
@@ -2858,30 +2910,25 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { | |
} | ||
} | ||
|
||
impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T> | ||
where | ||
B: TypeFoldable<'tcx>, | ||
V: TypeFoldable<'tcx>, | ||
T: TypeFoldable<'tcx>, | ||
impl<'tcx, V, T> TypeFoldable<'tcx> for ProjectionElem<'tcx, V, T> | ||
where V: TypeFoldable<'tcx>, | ||
T: TypeFoldable<'tcx> | ||
{ | ||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { | ||
use mir::ProjectionElem::*; | ||
|
||
let base = self.base.fold_with(folder); | ||
let elem = match self.elem { | ||
match *self { | ||
Deref => Deref, | ||
Field(f, ref ty) => Field(f, ty.fold_with(folder)), | ||
Index(ref v) => Index(v.fold_with(folder)), | ||
ref elem => elem.clone(), | ||
}; | ||
|
||
Projection { base, elem } | ||
} | ||
} | ||
|
||
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool { | ||
use mir::ProjectionElem::*; | ||
|
||
self.base.visit_with(visitor) || match self.elem { | ||
match *self { | ||
Field(_, ref ty) => ty.visit_with(visitor), | ||
Index(ref v) => v.visit_with(visitor), | ||
_ => false, | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO such a method is a hazard. All users should iterate over the
elems
vector.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I agree with "hazard", but I think a name like
last_projection
would be good. Also, can the return type beOption<&'tcx PlaceElem>
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a hazard to me as well. Better naming would help here, but I don’t see any reason against just inspecting the slice in-place.