From a0700d062e242940cf9e5644211f2be38e3d88eb Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 24 May 2019 00:40:41 +0200 Subject: [PATCH 1/2] Inline move_path_for_projection inside move_path_for --- .../dataflow/move_paths/builder.rs | 114 ++++++++---------- 1 file changed, 53 insertions(+), 61 deletions(-) diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 7eb4428bf29..507e5a4abab 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -101,7 +101,59 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { Err(MoveError::cannot_move_out_of(self.loc, Static)) } Place::Projection(ref proj) => { - self.move_path_for_projection(place, proj) + let base = self.move_path_for(&proj.base)?; + let mir = self.builder.mir; + let tcx = self.builder.tcx; + let place_ty = proj.base.ty(mir, tcx).ty; + match place_ty.sty { + ty::Ref(..) | ty::RawPtr(..) => + return Err(MoveError::cannot_move_out_of( + self.loc, + BorrowedContent { target_place: place.clone() })), + ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => + return Err(MoveError::cannot_move_out_of(self.loc, + InteriorOfTypeWithDestructor { + container_ty: place_ty + })), + // move out of union - always move the entire union + ty::Adt(adt, _) if adt.is_union() => + return Err(MoveError::UnionMove { path: base }), + ty::Slice(_) => + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfSliceOrArray { + ty: place_ty, is_index: match proj.elem { + ProjectionElem::Index(..) => true, + _ => false + }, + })), + ty::Array(..) => match proj.elem { + ProjectionElem::Index(..) => + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfSliceOrArray { + ty: place_ty, is_index: true + })), + _ => { + // FIXME: still badly broken + } + }, + _ => {} + }; + match self.builder.data.rev_lookup.projections.entry((base, proj.elem.lift())) { + Entry::Occupied(ent) => Ok(*ent.get()), + Entry::Vacant(ent) => { + let path = MoveDataBuilder::new_move_path( + &mut self.builder.data.move_paths, + &mut self.builder.data.path_map, + &mut self.builder.data.init_path_map, + Some(base), + place.clone() + ); + ent.insert(path); + Ok(path) + } + } } } } @@ -111,66 +163,6 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { // drop), so this not being a valid move path is OK. let _ = self.move_path_for(place); } - - fn move_path_for_projection(&mut self, - place: &Place<'tcx>, - proj: &Projection<'tcx>) - -> Result> - { - let base = self.move_path_for(&proj.base)?; - let mir = self.builder.mir; - let tcx = self.builder.tcx; - let place_ty = proj.base.ty(mir, tcx).ty; - match place_ty.sty { - ty::Ref(..) | ty::RawPtr(..) => - return Err(MoveError::cannot_move_out_of( - self.loc, - BorrowedContent { target_place: place.clone() })), - ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => - return Err(MoveError::cannot_move_out_of(self.loc, - InteriorOfTypeWithDestructor { - container_ty: place_ty - })), - // move out of union - always move the entire union - ty::Adt(adt, _) if adt.is_union() => - return Err(MoveError::UnionMove { path: base }), - ty::Slice(_) => - return Err(MoveError::cannot_move_out_of( - self.loc, - InteriorOfSliceOrArray { - ty: place_ty, is_index: match proj.elem { - ProjectionElem::Index(..) => true, - _ => false - }, - })), - ty::Array(..) => match proj.elem { - ProjectionElem::Index(..) => - return Err(MoveError::cannot_move_out_of( - self.loc, - InteriorOfSliceOrArray { - ty: place_ty, is_index: true - })), - _ => { - // FIXME: still badly broken - } - }, - _ => {} - }; - match self.builder.data.rev_lookup.projections.entry((base, proj.elem.lift())) { - Entry::Occupied(ent) => Ok(*ent.get()), - Entry::Vacant(ent) => { - let path = MoveDataBuilder::new_move_path( - &mut self.builder.data.move_paths, - &mut self.builder.data.path_map, - &mut self.builder.data.init_path_map, - Some(base), - place.clone() - ); - ent.insert(path); - Ok(path) - } - } - } } impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> { From 294dc18208e8338631a30767ed0394066638eabf Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 24 May 2019 00:52:10 +0200 Subject: [PATCH 2/2] Make move_path_for iterate instead of recurse --- .../dataflow/move_paths/builder.rs | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 507e5a4abab..ab0a2d87302 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -95,13 +95,15 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { -> Result> { debug!("lookup({:?})", place); - match *place { - Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]), - Place::Base(PlaceBase::Static(..)) => { - Err(MoveError::cannot_move_out_of(self.loc, Static)) - } - Place::Projection(ref proj) => { - let base = self.move_path_for(&proj.base)?; + place.iterate(|place_base, place_projection| { + let mut base = match place_base { + PlaceBase::Local(local) => self.builder.data.rev_lookup.locals[*local], + PlaceBase::Static(..) => { + return Err(MoveError::cannot_move_out_of(self.loc, Static)); + } + }; + + for proj in place_projection { let mir = self.builder.mir; let tcx = self.builder.tcx; let place_ty = proj.base.ty(mir, tcx).ty; @@ -109,7 +111,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { ty::Ref(..) | ty::RawPtr(..) => return Err(MoveError::cannot_move_out_of( self.loc, - BorrowedContent { target_place: place.clone() })), + BorrowedContent { + target_place: Place::Projection(Box::new(proj.clone())), + })), ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => return Err(MoveError::cannot_move_out_of(self.loc, InteriorOfTypeWithDestructor { @@ -140,22 +144,31 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { }, _ => {} }; - match self.builder.data.rev_lookup.projections.entry((base, proj.elem.lift())) { - Entry::Occupied(ent) => Ok(*ent.get()), + + base = match self + .builder + .data + .rev_lookup + .projections + .entry((base, proj.elem.lift())) + { + Entry::Occupied(ent) => *ent.get(), Entry::Vacant(ent) => { let path = MoveDataBuilder::new_move_path( &mut self.builder.data.move_paths, &mut self.builder.data.path_map, &mut self.builder.data.init_path_map, Some(base), - place.clone() + Place::Projection(Box::new(proj.clone())), ); ent.insert(path); - Ok(path) + path } - } + }; } - } + + Ok(base) + }) } fn create_move_path(&mut self, place: &Place<'tcx>) {