From 5de9cb0703555ee6e2e0af8305be138f09545485 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 19:36:48 -0300 Subject: [PATCH 01/12] super_ty on MutVisitor is empty so avoid the call --- src/librustc_mir/transform/erase_regions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 38a04ce8f3815..e9ce84a25838f 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -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) { From e069e9ccacbe92de1c893be5ad77fd5d6173f937 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 16:39:20 -0300 Subject: [PATCH 02/12] Prepare promote_consts MutVisitor to have projections interned --- src/librustc_mir/transform/promote_consts.rs | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 5d241ffe1c06a..d1c79c5ae2ada 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -191,6 +191,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { }); } + fn is_temp_kind(&self, local: Local) -> bool { + self.source.local_kind(local) == LocalKind::Temp + } + /// Copies the initialization of this temp to the /// promoted MIR, recursing through temps. fn promote_temp(&mut self, temp: Local) -> Local { @@ -396,10 +400,30 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { local: &mut Local, _: PlaceContext, _: Location) { - if self.source.local_kind(*local) == LocalKind::Temp { + if self.is_temp_kind(*local) { *local = self.promote_temp(*local); } } + + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + match elem { + PlaceElem::Index(local) if self.is_temp_kind(*local) => { + PlaceElem::Index(self.promote_temp(*local)) + } + _ => elem.clone(), + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } pub fn promote_candidates<'tcx>( From 591cc9aede4aec9b8816b8489eb98c2f2a3bfe90 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 17:58:28 -0300 Subject: [PATCH 03/12] Prepare simplify MutVisitor to have projections interned --- src/librustc_mir/transform/simplify.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 9ffff9a92fa53..57bc1c8fab969 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -366,7 +366,27 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater { }); self.super_basic_block_data(block, data); } + fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) { *l = self.map[*l].unwrap(); } + + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + if let PlaceElem::Index(local) = elem { + PlaceElem::Index(self.map[*local].unwrap()) + } else { + elem.clone() + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } From bb7d6d1c70964d1d3efd5fb448538b7de50bbe3c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 18:15:19 -0300 Subject: [PATCH 04/12] Prepare renumber MutVisitor to have projections interned --- src/librustc_mir/borrow_check/nll/renumber.rs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 88ad1fb129509..6eb5735cb16ba 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,7 +1,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::mir::{Location, Body, Promoted}; -use rustc::mir::visit::{MutVisitor, TyContext}; +use rustc::mir::{Body, Location, Place, PlaceElem, Promoted}; +use rustc::mir::visit::{MutVisitor, PlaceContext, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; @@ -62,6 +62,25 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { debug!("visit_ty: ty={:?}", ty); } + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + if let PlaceElem::Field(field, ty) = elem { + PlaceElem::Field(*field, self.renumber_regions(ty)) + } else { + elem.clone() + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } + fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { debug!("visit_substs(substs={:?}, location={:?})", substs, location); From e3e99516730f72fa05cb964ae341156e1ca85c39 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 18:23:39 -0300 Subject: [PATCH 05/12] Prepare inline MutVisitor to have projections interned --- src/librustc_mir/transform/inline.rs | 51 +++++++++++++++++++--------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 9830ed35ffc3e..3a71d22da7873 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -647,38 +647,45 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> { debug!("updating target `{:?}`, new: `{:?}`", tgt, new); new } -} -impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { - fn visit_local(&mut self, - local: &mut Local, - _ctxt: PlaceContext, - _location: Location) { + fn make_integrate_local(&self, local: &Local) -> Local { if *local == RETURN_PLACE { match self.destination { Place { base: PlaceBase::Local(l), projection: box [], } => { - *local = l; - return; + return l; }, ref place => bug!("Return place is {:?}, not local", place) } } + let idx = local.index() - 1; if idx < self.args.len() { - *local = self.args[idx]; - return; + return self.args[idx]; } - *local = self.local_map[Local::new(idx - self.args.len())]; + + self.local_map[Local::new(idx - self.args.len())] } +} - fn visit_place(&mut self, - place: &mut Place<'tcx>, - _ctxt: PlaceContext, - _location: Location) { +impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { + fn visit_local( + &mut self, + local: &mut Local, + _ctxt: PlaceContext, + _location: Location, + ) { + *local = self.make_integrate_local(local); + } + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { match place { Place { base: PlaceBase::Local(RETURN_PLACE), @@ -687,7 +694,19 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { // Return pointer; update the place itself *place = self.destination.clone(); }, - _ => self.super_place(place, _ctxt, _location) + _ => { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + if let PlaceElem::Index(local) = elem { + PlaceElem::Index(self.make_integrate_local(local)) + } else { + elem.clone() + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } } From 0fc063f15936761024183a3bb3790684d5de3bd3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 19:14:35 -0300 Subject: [PATCH 06/12] Prepare generator MutVisitor to have projections interned --- src/librustc_mir/transform/generator.rs | 52 +++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 865fa012c2995..a801548efab08 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -88,6 +88,24 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor { *local = self.to; } } + + fn visit_place(&mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + match elem { + PlaceElem::Index(local) if *local == self.from => { + PlaceElem::Index(self.to) + } + _ => elem.clone(), + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } struct DerefArgVisitor; @@ -110,7 +128,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()); + } + } } } } @@ -137,7 +161,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()); + } + } } } } @@ -247,17 +277,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()); + } + } } } From 39c9ed3ac19b3f6c79069d32a317daa763371369 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 19:35:41 -0300 Subject: [PATCH 07/12] Prepare erase_regions MutVisitor to have projections interned --- src/librustc_mir/transform/erase_regions.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index e9ce84a25838f..132149d5d4337 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::*; -use rustc::mir::visit::{MutVisitor, TyContext}; +use rustc::mir::visit::{MutVisitor, PlaceContext, TyContext}; use crate::transform::{MirPass, MirSource}; struct EraseRegionsVisitor<'tcx> { @@ -38,6 +38,25 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) { *substs = self.tcx.erase_regions(substs); } + + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + if let PlaceElem::Field(field, ty) = elem { + PlaceElem::Field(*field, self.tcx.erase_regions(ty)) + } else { + elem.clone() + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } pub struct EraseRegions; From 2b2e35bfc34618cff7b62a7726ee3a97101d3fa2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 00:24:18 -0300 Subject: [PATCH 08/12] Prepare def_use MutVisitor to have projections interned --- src/librustc_mir/util/def_use.rs | 36 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 3aea25fa8769f..d90be90bd9d49 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -1,6 +1,6 @@ //! Def-use analysis. -use rustc::mir::{Local, Location, Body}; +use rustc::mir::{Body, Local, Location, Place, PlaceElem}; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; use rustc_index::vec::IndexVec; use std::mem; @@ -47,13 +47,13 @@ impl DefUseAnalysis { &self.info[local] } - fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, mut callback: F) - where F: for<'a> FnMut(&'a mut Local, + fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, callback: F) + where F: for<'a> Fn(&'a Local, PlaceContext, - Location) { + Location) -> Local { for place_use in &self.info[local].defs_and_uses { MutateUseVisitor::new(local, - &mut callback, + &callback, body).visit_location(body, place_use.location) } } @@ -63,7 +63,7 @@ impl DefUseAnalysis { local: Local, body: &mut Body<'_>, new_local: Local) { - self.mutate_defs_and_uses(local, body, |local, _, _| *local = new_local) + self.mutate_defs_and_uses(local, body, |_, _, _| new_local) } } @@ -125,7 +125,7 @@ struct MutateUseVisitor { impl MutateUseVisitor { fn new(query: Local, callback: F, _: &Body<'_>) -> MutateUseVisitor - where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) { + where F: for<'a> Fn(&'a Local, PlaceContext, Location) -> Local { MutateUseVisitor { query, callback, @@ -134,13 +134,31 @@ impl MutateUseVisitor { } impl MutVisitor<'_> for MutateUseVisitor - where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) { + where F: for<'a> Fn(&'a Local, PlaceContext, Location) -> Local { fn visit_local(&mut self, local: &mut Local, context: PlaceContext, location: Location) { if *local == self.query { - (self.callback)(local, context, location) + *local = (self.callback)(local, context, location) } } + + fn visit_place(&mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + match elem { + PlaceElem::Index(local) if *local == self.query => { + PlaceElem::Index((self.callback)(&local, context, location)) + } + _ => elem.clone(), + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } From 4f2a11036d085227e261824a1aa76dd752c84267 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 00:33:47 -0300 Subject: [PATCH 09/12] Remove unneeded callback and just use the new_local value --- src/librustc_mir/util/def_use.rs | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index d90be90bd9d49..5b5f7d83f0746 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -47,13 +47,10 @@ impl DefUseAnalysis { &self.info[local] } - fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, callback: F) - where F: for<'a> Fn(&'a Local, - PlaceContext, - Location) -> Local { + fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, new_local: Local) { for place_use in &self.info[local].defs_and_uses { MutateUseVisitor::new(local, - &callback, + new_local, body).visit_location(body, place_use.location) } } @@ -63,7 +60,7 @@ impl DefUseAnalysis { local: Local, body: &mut Body<'_>, new_local: Local) { - self.mutate_defs_and_uses(local, body, |_, _, _| new_local) + self.mutate_defs_and_uses(local, body, new_local) } } @@ -117,30 +114,27 @@ impl Info { } } -struct MutateUseVisitor { +struct MutateUseVisitor { query: Local, - callback: F, + new_local: Local, } -impl MutateUseVisitor { - fn new(query: Local, callback: F, _: &Body<'_>) - -> MutateUseVisitor - where F: for<'a> Fn(&'a Local, PlaceContext, Location) -> Local { +impl MutateUseVisitor { + fn new(query: Local, new_local: Local, _: &Body<'_>) -> MutateUseVisitor { MutateUseVisitor { query, - callback, + new_local, } } } -impl MutVisitor<'_> for MutateUseVisitor - where F: for<'a> Fn(&'a Local, PlaceContext, Location) -> Local { +impl MutVisitor<'_> for MutateUseVisitor { fn visit_local(&mut self, local: &mut Local, - context: PlaceContext, - location: Location) { + _context: PlaceContext, + _location: Location) { if *local == self.query { - *local = (self.callback)(local, context, location) + *local = self.new_local; } } @@ -153,7 +147,7 @@ impl MutVisitor<'_> for MutateUseVisitor let new_projection: Vec<_> = place.projection.iter().map(|elem| match elem { PlaceElem::Index(local) if *local == self.query => { - PlaceElem::Index((self.callback)(&local, context, location)) + PlaceElem::Index(self.new_local) } _ => elem.clone(), } From 7fa3425ef675b4bf4177dc2ea232078f4556b4c4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 12:16:26 -0300 Subject: [PATCH 10/12] Setup a different visit place set of methods for mutable and immutable visitors In particular, use a blank visit_place for mutable visitor to be sure, non modified visitors are not trying to mutating place. --- src/librustc/mir/visit.rs | 180 ++++++++++++++++++++++---------------- 1 file changed, 103 insertions(+), 77 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index edc7922f46eec..0fb43c7f98d16 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -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>, @@ -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, @@ -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>) { @@ -858,6 +782,108 @@ macro_rules! make_mir_visitor { } } +macro_rules! visit_place_fns { + (mut) => ( + fn super_place( + &mut self, + _place: &mut Place<'tcx>, + _context: PlaceContext, + _location: Location, + ) { + } + ); + + () => ( + 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); From d53fc9cae5b17c138be09383dea8b8f10d3df3a1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 15:33:19 -0300 Subject: [PATCH 11/12] Add process_* place hooks to improve code reutilization --- src/librustc/mir/visit.rs | 28 +++++++++++++++++-- src/librustc_mir/borrow_check/nll/renumber.rs | 28 +++++++------------ src/librustc_mir/transform/erase_regions.rs | 26 ++++++----------- src/librustc_mir/transform/inline.rs | 23 +++++++-------- src/librustc_mir/transform/promote_consts.rs | 24 ++++++---------- src/librustc_mir/transform/simplify.rs | 24 ++++++---------- src/librustc_mir/util/def_use.rs | 26 +++++++---------- 7 files changed, 82 insertions(+), 97 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 0fb43c7f98d16..c8a6367899ba9 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -786,10 +786,32 @@ macro_rules! visit_place_fns { (mut) => ( fn super_place( &mut self, - _place: &mut Place<'tcx>, - _context: PlaceContext, - _location: Location, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, ) { + self.visit_place_base(&mut place.base, context, location); + + place.projection = self.process_projection(&place.projection); + } + + fn process_projection( + &mut self, + projection: &Box<[PlaceElem<'tcx>]>, + ) -> Box<[PlaceElem<'tcx>]> { + let new_projection: Vec<_> = projection.iter().map(|elem| + self.process_projection_elem(elem) + ).collect(); + + new_projection.into_boxed_slice() + } + + fn process_projection_elem( + &mut self, + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + // FIXME: avoid cloning here + elem.clone() } ); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 6eb5735cb16ba..c4a19ce5128b5 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,7 +1,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::mir::{Body, Location, Place, PlaceElem, Promoted}; -use rustc::mir::visit::{MutVisitor, PlaceContext, TyContext}; +use rustc::mir::{Body, Location, PlaceElem, Promoted}; +use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; @@ -62,23 +62,15 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { debug!("visit_ty: ty={:?}", ty); } - fn visit_place( + fn process_projection_elem( &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.renumber_regions(ty)) - } else { - elem.clone() - } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + if let PlaceElem::Field(field, ty) = elem { + PlaceElem::Field(*field, self.renumber_regions(ty)) + } else { + elem.clone() + } } fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 132149d5d4337..725a8de8fe7d1 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::*; -use rustc::mir::visit::{MutVisitor, PlaceContext, TyContext}; +use rustc::mir::visit::{MutVisitor, TyContext}; use crate::transform::{MirPass, MirSource}; struct EraseRegionsVisitor<'tcx> { @@ -39,23 +39,15 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { *substs = self.tcx.erase_regions(substs); } - fn visit_place( + fn process_projection_elem( &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.tcx.erase_regions(ty)) - } else { - elem.clone() - } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + if let PlaceElem::Field(field, ty) = elem { + PlaceElem::Field(*field, self.tcx.erase_regions(ty)) + } else { + elem.clone() + } } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 3a71d22da7873..dd13d0c96557d 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -695,21 +695,22 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { *place = self.destination.clone(); }, _ => { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - if let PlaceElem::Index(local) = elem { - PlaceElem::Index(self.make_integrate_local(local)) - } else { - elem.clone() - } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + self.super_place(place, context, location); } } } + fn process_projection_elem( + &mut self, + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + if let PlaceElem::Index(local) = elem { + PlaceElem::Index(self.make_integrate_local(local)) + } else { + elem.clone() + } + } + fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { self.in_cleanup_block = data.is_cleanup; self.super_basic_block_data(block, data); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index d1c79c5ae2ada..565f260546bc7 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -405,24 +405,16 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { } } - fn visit_place( + fn process_projection_elem( &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - match elem { - PlaceElem::Index(local) if self.is_temp_kind(*local) => { - PlaceElem::Index(self.promote_temp(*local)) - } - _ => elem.clone(), + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + match elem { + PlaceElem::Index(local) if self.is_temp_kind(*local) => { + PlaceElem::Index(self.promote_temp(*local)) } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + _ => elem.clone(), + } } } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 57bc1c8fab969..7dca3e357cc94 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -371,22 +371,14 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater { *l = self.map[*l].unwrap(); } - fn visit_place( + fn process_projection_elem( &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - if let PlaceElem::Index(local) = elem { - PlaceElem::Index(self.map[*local].unwrap()) - } else { - elem.clone() - } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + if let PlaceElem::Index(local) = elem { + PlaceElem::Index(self.map[*local].unwrap()) + } else { + elem.clone() + } } } diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 5b5f7d83f0746..25930df020aa9 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -1,6 +1,6 @@ //! Def-use analysis. -use rustc::mir::{Body, Local, Location, Place, PlaceElem}; +use rustc::mir::{Body, Local, Location, PlaceElem}; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; use rustc_index::vec::IndexVec; use std::mem; @@ -138,21 +138,15 @@ impl MutVisitor<'_> for MutateUseVisitor { } } - fn visit_place(&mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - match elem { - PlaceElem::Index(local) if *local == self.query => { - PlaceElem::Index(self.new_local) - } - _ => elem.clone(), + fn process_projection_elem( + &mut self, + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + match elem { + PlaceElem::Index(local) if *local == self.query => { + PlaceElem::Index(self.new_local) } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + _ => elem.clone(), + } } } From 48349960e68a9d19b17ac54cd12e939a9a46ea7d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 23:46:14 -0300 Subject: [PATCH 12/12] Use Cow to handle modifications of projection in preparation for interning --- src/librustc/mir/visit.rs | 33 ++++++++++++------- src/librustc_mir/borrow_check/nll/renumber.rs | 12 ++++--- src/librustc_mir/transform/erase_regions.rs | 12 ++++--- src/librustc_mir/transform/generator.rs | 24 +++++--------- src/librustc_mir/transform/inline.rs | 12 ++++--- src/librustc_mir/transform/promote_consts.rs | 6 ++-- src/librustc_mir/transform/simplify.rs | 11 ++++--- src/librustc_mir/util/def_use.rs | 6 ++-- 8 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index c8a6367899ba9..fef406e898783 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -792,26 +792,37 @@ macro_rules! visit_place_fns { ) { self.visit_place_base(&mut place.base, context, location); - place.projection = self.process_projection(&place.projection); + if let Some(new_projection) = self.process_projection(&place.projection) { + place.projection = new_projection; + } } fn process_projection( &mut self, - projection: &Box<[PlaceElem<'tcx>]>, - ) -> Box<[PlaceElem<'tcx>]> { - let new_projection: Vec<_> = projection.iter().map(|elem| - self.process_projection_elem(elem) - ).collect(); + projection: &'a [PlaceElem<'tcx>], + ) -> Option]>> { + 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; + } + } + } - new_projection.into_boxed_slice() + match projection { + Cow::Borrowed(_) => None, + Cow::Owned(vec) => Some(vec.into_boxed_slice()), + } } fn process_projection_elem( &mut self, - elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { - // FIXME: avoid cloning here - elem.clone() + _elem: &PlaceElem<'tcx>, + ) -> Option> { + None } ); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c4a19ce5128b5..9ecd6f837750e 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -65,12 +65,16 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.renumber_regions(ty)) - } else { - elem.clone() + 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) { diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 725a8de8fe7d1..439cae2093ae5 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -42,12 +42,16 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.tcx.erase_regions(ty)) - } else { - elem.clone() + let new_ty = self.tcx.erase_regions(ty); + + if new_ty != *ty { + return Some(PlaceElem::Field(*field, new_ty)); + } } + + None } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a801548efab08..6533e3c5ba81f 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -89,22 +89,16 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor { } } - fn visit_place(&mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - match elem { - PlaceElem::Index(local) if *local == self.from => { - PlaceElem::Index(self.to) - } - _ => elem.clone(), + fn process_projection_elem( + &mut self, + elem: &PlaceElem<'tcx>, + ) -> Option> { + match elem { + PlaceElem::Index(local) if *local == self.from => { + Some(PlaceElem::Index(self.to)) } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + _ => None, + } } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index dd13d0c96557d..0cbdcedff4780 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -703,12 +703,16 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { if let PlaceElem::Index(local) = elem { - PlaceElem::Index(self.make_integrate_local(local)) - } else { - elem.clone() + let new_local = self.make_integrate_local(local); + + if new_local != *local { + return Some(PlaceElem::Index(new_local)) + } } + + None } fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 565f260546bc7..ad1785417cd93 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -408,12 +408,12 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { match elem { PlaceElem::Index(local) if self.is_temp_kind(*local) => { - PlaceElem::Index(self.promote_temp(*local)) + Some(PlaceElem::Index(self.promote_temp(*local))) } - _ => elem.clone(), + _ => None, } } } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 7dca3e357cc94..606c1a3a1cc09 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -374,11 +374,12 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { - if let PlaceElem::Index(local) = elem { - PlaceElem::Index(self.map[*local].unwrap()) - } else { - elem.clone() + ) -> Option> { + match elem { + PlaceElem::Index(local) => { + Some(PlaceElem::Index(self.map[*local].unwrap())) + } + _ => None } } } diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 25930df020aa9..cdd07ad4b8ff4 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -141,12 +141,12 @@ impl MutVisitor<'_> for MutateUseVisitor { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { match elem { PlaceElem::Index(local) if *local == self.query => { - PlaceElem::Index(self.new_local) + Some(PlaceElem::Index(self.new_local)) } - _ => elem.clone(), + _ => None, } } }