-
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
Changes from 1 commit
357bc2c
34329c0
bd9f156
85a87a1
a5c428b
6002649
b1dbe6f
c5a7e57
e684ea3
091802d
c1fff48
56773a9
36b5cac
2cd7680
ec40255
7b65566
a6520ec
fea2e88
244fbb4
73e86a2
5aae53e
9ec03b3
2af0dd0
6045a8a
e912a26
13a9c20
d5095f6
6f8aa3d
7da7205
c47b2a9
8616672
ba7feb1
552a935
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 | ||
|
@@ -1731,7 +1737,7 @@ pub struct Projection<'tcx, B, V, T> { | |
pub elem: ProjectionElem<'tcx, V, T>, | ||
} | ||
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. The |
||
|
||
#[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), | ||
|
@@ -1779,31 +1785,52 @@ 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() | ||
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. IMO such a method is a hazard. All users should iterate over the 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. I'm not sure I agree with "hazard", but I think a name like 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. 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. |
||
} | ||
|
||
pub fn deref(self) -> Place<'tcx> { | ||
self.elem(ProjectionElem::Deref) | ||
pub fn field( | ||
self, | ||
tcx: TyCtxt<'a, 'tcx, 'tcx>, | ||
f: Field, | ||
ty: Ty<'tcx>, | ||
) -> Self { | ||
self.elem(tcx, ProjectionElem::Field(f, ty)) | ||
} | ||
|
||
pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> { | ||
self.elem(ProjectionElem::Downcast(adt_def, variant_index)) | ||
pub fn deref(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { | ||
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. I think this should be |
||
self.elem(tcx, ProjectionElem::Deref) | ||
} | ||
|
||
pub fn index(self, index: Local) -> Place<'tcx> { | ||
self.elem(ProjectionElem::Index(index)) | ||
pub fn downcast( | ||
self, | ||
tcx: TyCtxt<'a, 'tcx, 'tcx>, | ||
adt_def: &'tcx AdtDef, variant_index: usize, | ||
) -> Self { | ||
self.elem(tcx, ProjectionElem::Downcast(adt_def, variant_index)) | ||
} | ||
|
||
pub fn index(self, tcx: TyCtxt<'a, 'tcx, 'tcx>, index: Local) -> Self { | ||
self.elem(tcx, ProjectionElem::Index(index)) | ||
} | ||
|
||
pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> { | ||
Place::Projection(Box::new(PlaceProjection { base: self, elem })) | ||
pub fn elem( | ||
self, | ||
tcx: TyCtxt<'a, 'tcx, 'tcx>, | ||
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. ...and here...etc |
||
elem: PlaceElem<'tcx>, | ||
) -> Self { | ||
Place { | ||
base: self.base, | ||
elems: tcx.intern_place_elems(&[elem]), | ||
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. This replaces the current 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. Minor nit. The builder pattern used here suggests that the
and thus having every slice for each intermediate projection interned. Not sure if this is a relevant problem or whether the current code would be able to take advantage of a one-shot method, though. |
||
} | ||
} | ||
} | ||
|
||
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 +1841,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 +2758,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,37 +2874,52 @@ 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, | ||
} | ||
} | ||
} | ||
|
||
impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T> | ||
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 { | ||
|
||
let base = self.base.fold_with(folder); | ||
let elem = self.elem.fold_with(folder); | ||
Projection { base, elem } | ||
} | ||
|
||
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool { | ||
|
||
self.base.visit_with(visitor) || | ||
self.elem.visit_with(visitor) | ||
} | ||
} | ||
|
||
impl<'tcx> TypeFoldable<'tcx> for Field { | ||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self { | ||
*self | ||
|
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.
You might be able to use one of the macros since this is just a struct now.