1- use crate :: move_paths:: FxHashMap ;
2- use crate :: un_derefer:: UnDerefer ;
31use rustc_index:: IndexVec ;
42use rustc_middle:: mir:: tcx:: RvalueInitializationState ;
53use rustc_middle:: mir:: * ;
64use rustc_middle:: ty:: { self , TyCtxt } ;
75use smallvec:: { smallvec, SmallVec } ;
86
7+ use std:: iter;
98use std:: mem;
109
1110use super :: abs_domain:: Lift ;
@@ -21,7 +20,6 @@ struct MoveDataBuilder<'a, 'tcx> {
2120 param_env : ty:: ParamEnv < ' tcx > ,
2221 data : MoveData < ' tcx > ,
2322 errors : Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > ,
24- un_derefer : UnDerefer < ' tcx > ,
2523}
2624
2725impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
@@ -35,25 +33,29 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
3533 tcx,
3634 param_env,
3735 errors : Vec :: new ( ) ,
38- un_derefer : UnDerefer { tcx : tcx, derefer_sidetable : Default :: default ( ) } ,
3936 data : MoveData {
4037 moves : IndexVec :: new ( ) ,
4138 loc_map : LocationMap :: new ( body) ,
4239 rev_lookup : MovePathLookup {
4340 locals : body
4441 . local_decls
45- . indices ( )
46- . map ( |i| {
47- Self :: new_move_path (
48- & mut move_paths,
49- & mut path_map,
50- & mut init_path_map,
51- None ,
52- Place :: from ( i) ,
42+ . iter_enumerated ( )
43+ . filter ( |( _, l) | !l. is_deref_temp ( ) )
44+ . map ( |( i, _) | {
45+ (
46+ i,
47+ Self :: new_move_path (
48+ & mut move_paths,
49+ & mut path_map,
50+ & mut init_path_map,
51+ None ,
52+ Place :: from ( i) ,
53+ ) ,
5354 )
5455 } )
5556 . collect ( ) ,
5657 projections : Default :: default ( ) ,
58+ derefer_sidetable : Default :: default ( ) ,
5759 } ,
5860 move_paths,
5961 path_map,
@@ -98,13 +100,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
98100 ///
99101 /// Maybe we should have separate "borrowck" and "moveck" modes.
100102 fn move_path_for ( & mut self , place : Place < ' tcx > ) -> Result < MovePathIndex , MoveError < ' tcx > > {
101- if let Some ( new_place) = self . builder . un_derefer . derefer ( place. as_ref ( ) , self . builder . body )
102- {
103- return self . move_path_for ( new_place) ;
104- }
103+ let deref_chain = self . builder . data . rev_lookup . deref_chain ( place. as_ref ( ) ) ;
105104
106105 debug ! ( "lookup({:?})" , place) ;
107- let mut base = self . builder . data . rev_lookup . locals [ place. local ] ;
106+ let mut base =
107+ self . builder . data . rev_lookup . find_local ( deref_chain. first ( ) . unwrap_or ( & place) . local ) ;
108108
109109 // The move path index of the first union that we find. Once this is
110110 // some we stop creating child move paths, since moves from unions
@@ -113,51 +113,55 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
113113 // from `*(u.f: &_)` isn't allowed.
114114 let mut union_path = None ;
115115
116- for ( place_ref, elem) in place. as_ref ( ) . iter_projections ( ) {
117- let body = self . builder . body ;
118- let tcx = self . builder . tcx ;
119- let place_ty = place_ref. ty ( body, tcx) . ty ;
120-
121- match place_ty. kind ( ) {
122- ty:: Ref ( ..) | ty:: RawPtr ( ..) => {
123- return Err ( MoveError :: cannot_move_out_of (
124- self . loc ,
125- BorrowedContent { target_place : place_ref. project_deeper ( & [ elem] , tcx) } ,
126- ) ) ;
127- }
128- ty:: Adt ( adt, _) if adt. has_dtor ( tcx) && !adt. is_box ( ) => {
129- return Err ( MoveError :: cannot_move_out_of (
130- self . loc ,
131- InteriorOfTypeWithDestructor { container_ty : place_ty } ,
132- ) ) ;
133- }
134- ty:: Adt ( adt, _) if adt. is_union ( ) => {
135- union_path. get_or_insert ( base) ;
136- }
137- ty:: Slice ( _) => {
138- return Err ( MoveError :: cannot_move_out_of (
139- self . loc ,
140- InteriorOfSliceOrArray {
141- ty : place_ty,
142- is_index : matches ! ( elem, ProjectionElem :: Index ( ..) ) ,
143- } ,
144- ) ) ;
145- }
146-
147- ty:: Array ( ..) => {
148- if let ProjectionElem :: Index ( ..) = elem {
116+ for place in deref_chain. into_iter ( ) . chain ( iter:: once ( place) ) {
117+ for ( place_ref, elem) in place. as_ref ( ) . iter_projections ( ) {
118+ let body = self . builder . body ;
119+ let tcx = self . builder . tcx ;
120+ let place_ty = place_ref. ty ( body, tcx) . ty ;
121+ match place_ty. kind ( ) {
122+ ty:: Ref ( ..) | ty:: RawPtr ( ..) => {
149123 return Err ( MoveError :: cannot_move_out_of (
150124 self . loc ,
151- InteriorOfSliceOrArray { ty : place_ty, is_index : true } ,
125+ BorrowedContent {
126+ target_place : place_ref. project_deeper ( & [ elem] , tcx) ,
127+ } ,
128+ ) ) ;
129+ }
130+ ty:: Adt ( adt, _) if adt. has_dtor ( tcx) && !adt. is_box ( ) => {
131+ return Err ( MoveError :: cannot_move_out_of (
132+ self . loc ,
133+ InteriorOfTypeWithDestructor { container_ty : place_ty } ,
134+ ) ) ;
135+ }
136+ ty:: Adt ( adt, _) if adt. is_union ( ) => {
137+ union_path. get_or_insert ( base) ;
138+ }
139+ ty:: Slice ( _) => {
140+ return Err ( MoveError :: cannot_move_out_of (
141+ self . loc ,
142+ InteriorOfSliceOrArray {
143+ ty : place_ty,
144+ is_index : matches ! ( elem, ProjectionElem :: Index ( ..) ) ,
145+ } ,
152146 ) ) ;
153147 }
154- }
155148
156- _ => { }
157- } ;
149+ ty:: Array ( ..) => {
150+ if let ProjectionElem :: Index ( ..) = elem {
151+ return Err ( MoveError :: cannot_move_out_of (
152+ self . loc ,
153+ InteriorOfSliceOrArray { ty : place_ty, is_index : true } ,
154+ ) ) ;
155+ }
156+ }
157+
158+ _ => { }
159+ } ;
158160
159- if union_path. is_none ( ) {
160- base = self . add_move_path ( base, elem, |tcx| place_ref. project_deeper ( & [ elem] , tcx) ) ;
161+ if union_path. is_none ( ) {
162+ base = self
163+ . add_move_path ( base, elem, |tcx| place_ref. project_deeper ( & [ elem] , tcx) ) ;
164+ }
161165 }
162166 }
163167
@@ -198,10 +202,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
198202 }
199203}
200204
201- pub type MoveDat < ' tcx > = Result <
202- ( FxHashMap < Local , Place < ' tcx > > , MoveData < ' tcx > ) ,
203- ( MoveData < ' tcx > , Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > ) ,
204- > ;
205+ pub type MoveDat < ' tcx > =
206+ Result < MoveData < ' tcx > , ( MoveData < ' tcx > , Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > ) > ;
205207
206208impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
207209 fn finalize ( self ) -> MoveDat < ' tcx > {
@@ -217,11 +219,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
217219 "done dumping moves"
218220 } ) ;
219221
220- if self . errors . is_empty ( ) {
221- Ok ( ( self . un_derefer . derefer_sidetable , self . data ) )
222- } else {
223- Err ( ( self . data , self . errors ) )
224- }
222+ if self . errors . is_empty ( ) { Ok ( self . data ) } else { Err ( ( self . data , self . errors ) ) }
225223 }
226224}
227225
@@ -250,7 +248,7 @@ pub(super) fn gather_moves<'tcx>(
250248impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
251249 fn gather_args ( & mut self ) {
252250 for arg in self . body . args_iter ( ) {
253- let path = self . data . rev_lookup . locals [ arg] ;
251+ let path = self . data . rev_lookup . find_local ( arg) ;
254252
255253 let init = self . data . inits . push ( Init {
256254 path,
@@ -286,7 +284,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
286284 StatementKind :: Assign ( box ( place, Rvalue :: CopyForDeref ( reffed) ) ) => {
287285 assert ! ( place. projection. is_empty( ) ) ;
288286 if self . builder . body . local_decls [ place. local ] . is_deref_temp ( ) {
289- self . builder . un_derefer . derefer_sidetable . insert ( place. local , * reffed) ;
287+ self . builder . data . rev_lookup . derefer_sidetable . insert ( place. local , * reffed) ;
290288 }
291289 }
292290 StatementKind :: Assign ( box ( place, rval) ) => {
@@ -308,7 +306,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
308306 StatementKind :: StorageLive ( _) => { }
309307 StatementKind :: StorageDead ( local) => {
310308 // DerefTemp locals (results of CopyForDeref) don't actually move anything.
311- if !self . builder . un_derefer . derefer_sidetable . contains_key ( & local) {
309+ if !self . builder . data . rev_lookup . derefer_sidetable . contains_key ( & local) {
312310 self . gather_move ( Place :: from ( * local) ) ;
313311 }
314312 }
@@ -450,12 +448,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
450448
451449 fn gather_move ( & mut self , place : Place < ' tcx > ) {
452450 debug ! ( "gather_move({:?}, {:?})" , self . loc, place) ;
453- if let Some ( new_place) = self . builder . un_derefer . derefer ( place. as_ref ( ) , self . builder . body )
454- {
455- self . gather_move ( new_place) ;
456- return ;
457- }
458-
459451 if let [ ref base @ .., ProjectionElem :: Subslice { from, to, from_end : false } ] =
460452 * * place. projection
461453 {
@@ -512,11 +504,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
512504 fn gather_init ( & mut self , place : PlaceRef < ' tcx > , kind : InitKind ) {
513505 debug ! ( "gather_init({:?}, {:?})" , self . loc, place) ;
514506
515- if let Some ( new_place) = self . builder . un_derefer . derefer ( place, self . builder . body ) {
516- self . gather_init ( new_place. as_ref ( ) , kind) ;
517- return ;
518- }
519-
520507 let mut place = place;
521508
522509 // Check if we are assigning into a field of a union, if so, lookup the place
0 commit comments