From cdf33d9bc1016c154ef3d9df93413a5452bc04d0 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 23:46:14 -0300 Subject: [PATCH] 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 | 14 ++++---- src/librustc_mir/transform/erase_regions.rs | 14 ++++---- src/librustc_mir/transform/inline.rs | 14 ++++---- src/librustc_mir/transform/promote_consts.rs | 11 ++++--- src/librustc_mir/transform/simplify.rs | 13 ++++---- src/librustc_mir/util/def_use.rs | 11 ++++--- 7 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index c8a6367899ba9..0a6a6edf44816 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 Cow::Owned(elem) = self.process_projection_elem(Cow::Borrowed(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: Cow<'a, PlaceElem<'tcx>>, + ) -> Cow<'a, PlaceElem<'tcx>> { + elem } ); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c4a19ce5128b5..0073443817003 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -4,6 +4,7 @@ use rustc::mir::{Body, Location, PlaceElem, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; +use std::borrow::Cow; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. @@ -64,12 +65,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { fn process_projection_elem( &mut self, - elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { - if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.renumber_regions(ty)) - } else { - elem.clone() + elem: Cow<'b, PlaceElem<'tcx>>, + ) -> Cow<'b, PlaceElem<'tcx>> { + match elem { + Cow::Borrowed(PlaceElem::Field(field, ty)) => { + Cow::Owned(PlaceElem::Field(*field, self.renumber_regions(ty))) + } + _ => elem, } } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 725a8de8fe7d1..3ed87fccd7be8 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -9,6 +9,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::*; use rustc::mir::visit::{MutVisitor, TyContext}; use crate::transform::{MirPass, MirSource}; +use std::borrow::Cow; struct EraseRegionsVisitor<'tcx> { tcx: TyCtxt<'tcx>, @@ -41,12 +42,13 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { fn process_projection_elem( &mut self, - elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { - if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.tcx.erase_regions(ty)) - } else { - elem.clone() + elem: Cow<'a, PlaceElem<'tcx>>, + ) -> Cow<'a, PlaceElem<'tcx>> { + match elem { + Cow::Borrowed(PlaceElem::Field(field, ty)) => { + Cow::Owned(PlaceElem::Field(*field, self.tcx.erase_regions(ty))) + } + _ => elem, } } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index dd13d0c96557d..6a02985c8c260 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -11,6 +11,7 @@ use rustc::mir::visit::*; use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc::ty::subst::{Subst, SubstsRef}; +use std::borrow::Cow; use std::collections::VecDeque; use std::iter; use crate::transform::{MirPass, MirSource}; @@ -702,12 +703,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { 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() + elem: Cow<'b, PlaceElem<'tcx>>, + ) -> Cow<'b, PlaceElem<'tcx>> { + match elem { + Cow::Borrowed(PlaceElem::Index(local)) => { + Cow::Owned(PlaceElem::Index(self.make_integrate_local(local))) + } + _ => elem, } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 565f260546bc7..7b348b054175e 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -23,6 +23,7 @@ use syntax_pos::Span; use rustc_index::vec::{IndexVec, Idx}; use std::{iter, mem, usize}; +use std::borrow::Cow; /// State of a temporary during collection and promotion. #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -407,13 +408,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { fn process_projection_elem( &mut self, - elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + elem: Cow<'b, PlaceElem<'tcx>>, + ) -> Cow<'b, PlaceElem<'tcx>> { match elem { - PlaceElem::Index(local) if self.is_temp_kind(*local) => { - PlaceElem::Index(self.promote_temp(*local)) + Cow::Borrowed(PlaceElem::Index(local)) if self.is_temp_kind(*local) => { + Cow::Owned(PlaceElem::Index(self.promote_temp(*local))) } - _ => elem.clone(), + _ => elem, } } } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 7dca3e357cc94..b0199fe807d35 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -373,12 +373,13 @@ 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() + elem: Cow<'a, PlaceElem<'tcx>>, + ) -> Cow<'a, PlaceElem<'tcx>> { + match elem { + Cow::Borrowed(PlaceElem::Index(local)) => { + Cow::Owned(PlaceElem::Index(self.map[*local].unwrap())) + } + _ => elem, } } } diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 25930df020aa9..b7f89681e4d45 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -3,6 +3,7 @@ use rustc::mir::{Body, Local, Location, PlaceElem}; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; use rustc_index::vec::IndexVec; +use std::borrow::Cow; use std::mem; pub struct DefUseAnalysis { @@ -140,13 +141,13 @@ impl MutVisitor<'_> for MutateUseVisitor { fn process_projection_elem( &mut self, - elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + elem: Cow<'a, PlaceElem<'tcx>>, + ) -> Cow<'a, PlaceElem<'tcx>> { match elem { - PlaceElem::Index(local) if *local == self.query => { - PlaceElem::Index(self.new_local) + Cow::Borrowed(PlaceElem::Index(local)) if *local == self.query => { + Cow::Owned(PlaceElem::Index(self.new_local)) } - _ => elem.clone(), + _ => elem, } } }