Skip to content

Commit

Permalink
Rollup merge of rust-lang#65197 - spastorino:place-mut-visitor-adjust…
Browse files Browse the repository at this point in the history
…s2, r=oli-obk

Prepare `MutVisitor`s to handle interned projections

The following are all the files where mir's `MutVisitor` is implemented. The `-` there stands for no changes, `visit_place` wasn't making any change on `Place`s. `x` stands for this file was changed to make `visit_place` do whatever it was doing with the base but avoid modifying the projection, instead just create a new one and assign to it.

```
[-] src/librustc_mir/transform/no_landing_pads.rs
[x] src/librustc_mir/transform/promote_consts.rs
[x] src/librustc_mir/transform/generator.rs
[x] src/librustc_mir/transform/erase_regions.rs
[-] src/librustc_mir/transform/instcombine.rs
[x] src/librustc_mir/transform/inline.rs
[x] src/librustc_mir/transform/simplify.rs
[x] src/librustc_mir/util/def_use.rs
[-] src/librustc_mir/transform/const_prop.rs
[-] src/librustc_mir/transform/cleanup_post_borrowck.rs
[x] src/librustc_mir/borrow_check/nll/renumber.rs
[-] src/librustc_mir/transform/copy_prop.rs
```

There is some code repetition, just created the PR so we can start discussing it.

/cc @oli-obk @nikomatsakis
  • Loading branch information
tmandry authored Oct 18, 2019
2 parents 13e47c8 + 4834996 commit 53ba12c
Show file tree
Hide file tree
Showing 8 changed files with 301 additions and 122 deletions.
213 changes: 136 additions & 77 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,22 +158,7 @@ macro_rules! make_mir_visitor {
self.super_place_base(base, context, location);
}

fn visit_projection(&mut self,
base: & $($mutability)? PlaceBase<'tcx>,
projection: & $($mutability)? [PlaceElem<'tcx>],
context: PlaceContext,
location: Location) {
self.super_projection(base, projection, context, location);
}

fn visit_projection_elem(&mut self,
base: & $($mutability)? PlaceBase<'tcx>,
proj_base: & $($mutability)? [PlaceElem<'tcx>],
elem: & $($mutability)? PlaceElem<'tcx>,
context: PlaceContext,
location: Location) {
self.super_projection_elem(base, proj_base, elem, context, location);
}
visit_place_fns!($($mutability)?);

fn visit_constant(&mut self,
constant: & $($mutability)? Constant<'tcx>,
Expand Down Expand Up @@ -681,28 +666,6 @@ macro_rules! make_mir_visitor {
);
}

fn super_place(&mut self,
place: & $($mutability)? Place<'tcx>,
context: PlaceContext,
location: Location) {
let mut context = context;

if !place.projection.is_empty() {
context = if context.is_mutating_use() {
PlaceContext::MutatingUse(MutatingUseContext::Projection)
} else {
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
};
}

self.visit_place_base(& $($mutability)? place.base, context, location);

self.visit_projection(& $($mutability)? place.base,
& $($mutability)? place.projection,
context,
location);
}

fn super_place_base(&mut self,
place_base: & $($mutability)? PlaceBase<'tcx>,
context: PlaceContext,
Expand All @@ -717,45 +680,6 @@ macro_rules! make_mir_visitor {
}
}

fn super_projection(&mut self,
base: & $($mutability)? PlaceBase<'tcx>,
projection: & $($mutability)? [PlaceElem<'tcx>],
context: PlaceContext,
location: Location) {
let mut cursor = projection;
while let [proj_base @ .., elem] = cursor {
cursor = proj_base;
self.visit_projection_elem(base, cursor, elem, context, location);
}
}

fn super_projection_elem(&mut self,
_base: & $($mutability)? PlaceBase<'tcx>,
_proj_base: & $($mutability)? [PlaceElem<'tcx>],
elem: & $($mutability)? PlaceElem<'tcx>,
_context: PlaceContext,
location: Location) {
match elem {
ProjectionElem::Field(_field, ty) => {
self.visit_ty(ty, TyContext::Location(location));
}
ProjectionElem::Index(local) => {
self.visit_local(
local,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location
);
}
ProjectionElem::Deref |
ProjectionElem::Subslice { from: _, to: _ } |
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
from_end: _ } |
ProjectionElem::Downcast(_, _) => {
}
}
}

fn super_local_decl(&mut self,
local: Local,
local_decl: & $($mutability)? LocalDecl<'tcx>) {
Expand Down Expand Up @@ -858,6 +782,141 @@ macro_rules! make_mir_visitor {
}
}

macro_rules! visit_place_fns {
(mut) => (
fn super_place(
&mut self,
place: &mut Place<'tcx>,
context: PlaceContext,
location: Location,
) {
self.visit_place_base(&mut place.base, context, location);

if let Some(new_projection) = self.process_projection(&place.projection) {
place.projection = new_projection;
}
}

fn process_projection(
&mut self,
projection: &'a [PlaceElem<'tcx>],
) -> Option<Box<[PlaceElem<'tcx>]>> {
let mut projection = Cow::Borrowed(projection);

for i in 0..projection.len() {
if let Some(elem) = projection.get(i) {
if let Some(elem) = self.process_projection_elem(elem) {
let vec = projection.to_mut();
vec[i] = elem;
}
}
}

match projection {
Cow::Borrowed(_) => None,
Cow::Owned(vec) => Some(vec.into_boxed_slice()),
}
}

fn process_projection_elem(
&mut self,
_elem: &PlaceElem<'tcx>,
) -> Option<PlaceElem<'tcx>> {
None
}
);

() => (
fn visit_projection(
&mut self,
base: &PlaceBase<'tcx>,
projection: &[PlaceElem<'tcx>],
context: PlaceContext,
location: Location,
) {
self.super_projection(base, projection, context, location);
}

fn visit_projection_elem(
&mut self,
base: &PlaceBase<'tcx>,
proj_base: &[PlaceElem<'tcx>],
elem: &PlaceElem<'tcx>,
context: PlaceContext,
location: Location,
) {
self.super_projection_elem(base, proj_base, elem, context, location);
}

fn super_place(
&mut self,
place: &Place<'tcx>,
context: PlaceContext,
location: Location,
) {
let mut context = context;

if !place.projection.is_empty() {
context = if context.is_mutating_use() {
PlaceContext::MutatingUse(MutatingUseContext::Projection)
} else {
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
};
}

self.visit_place_base(&place.base, context, location);

self.visit_projection(&place.base,
&place.projection,
context,
location);
}

fn super_projection(
&mut self,
base: &PlaceBase<'tcx>,
projection: &[PlaceElem<'tcx>],
context: PlaceContext,
location: Location,
) {
let mut cursor = projection;
while let [proj_base @ .., elem] = cursor {
cursor = proj_base;
self.visit_projection_elem(base, cursor, elem, context, location);
}
}

fn super_projection_elem(
&mut self,
_base: &PlaceBase<'tcx>,
_proj_base: &[PlaceElem<'tcx>],
elem: &PlaceElem<'tcx>,
_context: PlaceContext,
location: Location,
) {
match elem {
ProjectionElem::Field(_field, ty) => {
self.visit_ty(ty, TyContext::Location(location));
}
ProjectionElem::Index(local) => {
self.visit_local(
local,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location
);
}
ProjectionElem::Deref |
ProjectionElem::Subslice { from: _, to: _ } |
ProjectionElem::ConstantIndex { offset: _,
min_length: _,
from_end: _ } |
ProjectionElem::Downcast(_, _) => {
}
}
}
);
}

make_mir_visitor!(Visitor,);
make_mir_visitor!(MutVisitor,mut);

Expand Down
17 changes: 16 additions & 1 deletion src/librustc_mir/borrow_check/nll/renumber.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::mir::{Location, Body, Promoted};
use rustc::mir::{Body, Location, PlaceElem, Promoted};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
use rustc_index::vec::IndexVec;
Expand Down Expand Up @@ -62,6 +62,21 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> {
debug!("visit_ty: ty={:?}", ty);
}

fn process_projection_elem(
&mut self,
elem: &PlaceElem<'tcx>,
) -> Option<PlaceElem<'tcx>> {
if let PlaceElem::Field(field, ty) = elem {
let new_ty = self.renumber_regions(ty);

if new_ty != *ty {
return Some(PlaceElem::Field(*field, new_ty));
}
}

None
}

fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
debug!("visit_substs(substs={:?}, location={:?})", substs, location);

Expand Down
16 changes: 15 additions & 1 deletion src/librustc_mir/transform/erase_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ impl EraseRegionsVisitor<'tcx> {
impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> {
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
*ty = self.tcx.erase_regions(ty);
self.super_ty(ty);
}

fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
Expand All @@ -39,6 +38,21 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> {
fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) {
*substs = self.tcx.erase_regions(substs);
}

fn process_projection_elem(
&mut self,
elem: &PlaceElem<'tcx>,
) -> Option<PlaceElem<'tcx>> {
if let PlaceElem::Field(field, ty) = elem {
let new_ty = self.tcx.erase_regions(ty);

if new_ty != *ty {
return Some(PlaceElem::Field(*field, new_ty));
}
}

None
}
}

pub struct EraseRegions;
Expand Down
46 changes: 39 additions & 7 deletions src/librustc_mir/transform/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor {
*local = self.to;
}
}

fn process_projection_elem(
&mut self,
elem: &PlaceElem<'tcx>,
) -> Option<PlaceElem<'tcx>> {
match elem {
PlaceElem::Index(local) if *local == self.from => {
Some(PlaceElem::Index(self.to))
}
_ => None,
}
}
}

struct DerefArgVisitor;
Expand All @@ -110,7 +122,13 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
projection: Box::new([ProjectionElem::Deref]),
});
} else {
self.super_place(place, context, location);
self.visit_place_base(&mut place.base, context, location);

for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
assert_ne!(*local, self_arg());
}
}
}
}
}
Expand All @@ -137,7 +155,13 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
projection: Box::new([ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]),
});
} else {
self.super_place(place, context, location);
self.visit_place_base(&mut place.base, context, location);

for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
assert_ne!(*local, self_arg());
}
}
}
}
}
Expand Down Expand Up @@ -247,17 +271,25 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
assert_eq!(self.remap.get(local), None);
}

fn visit_place(&mut self,
place: &mut Place<'tcx>,
context: PlaceContext,
location: Location) {
fn visit_place(
&mut self,
place: &mut Place<'tcx>,
context: PlaceContext,
location: Location,
) {
if let PlaceBase::Local(l) = place.base {
// Replace an Local in the remap with a generator struct access
if let Some(&(ty, variant_index, idx)) = self.remap.get(&l) {
replace_base(place, self.make_field(variant_index, idx, ty));
}
} else {
self.super_place(place, context, location);
self.visit_place_base(&mut place.base, context, location);

for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
assert_ne!(*local, self_arg());
}
}
}
}

Expand Down
Loading

0 comments on commit 53ba12c

Please sign in to comment.