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, } } }