@@ -4,7 +4,6 @@ use rustc_middle::mir::*;
44use  rustc_middle:: ty:: { self ,  TyCtxt } ; 
55use  smallvec:: { smallvec,  SmallVec } ; 
66
7- use  std:: iter; 
87use  std:: mem; 
98
109use  super :: abs_domain:: Lift ; 
@@ -40,22 +39,22 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
4039                    locals :  body
4140                        . local_decls 
4241                        . iter_enumerated ( ) 
43-                         . filter ( |( _ ,  l) | !l . is_deref_temp ( ) ) 
44-                         . map ( | ( i ,  _ ) |  { 
45-                             ( 
46-                                 i , 
42+                         . map ( |( i ,  l) | { 
43+                              if  l . is_deref_temp ( )  { 
44+                                  MovePathIndex :: MAX 
45+                             }   else   { 
4746                                Self :: new_move_path ( 
4847                                    & mut  move_paths, 
4948                                    & mut  path_map, 
5049                                    & mut  init_path_map, 
5150                                    None , 
5251                                    Place :: from ( i) , 
53-                                 ) , 
54-                             ) 
52+                                 ) 
53+                             } 
5554                        } ) 
5655                        . collect ( ) , 
5756                    projections :  Default :: default ( ) , 
58-                     derefer_sidetable :  Default :: default ( ) , 
57+                     un_derefer :  Default :: default ( ) , 
5958                } , 
6059                move_paths, 
6160                path_map, 
@@ -100,11 +99,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
10099/// 
101100/// Maybe we should have separate "borrowck" and "moveck" modes. 
102101fn  move_path_for ( & mut  self ,  place :  Place < ' tcx > )  -> Result < MovePathIndex ,  MoveError < ' tcx > >  { 
103-         let  deref_chain  = self . builder . data . rev_lookup . deref_chain ( place . as_ref ( ) ) ; 
102+         let  data  = & mut   self . builder . data ; 
104103
105104        debug ! ( "lookup({:?})" ,  place) ; 
106-         let  mut  base =
107-             self . builder . data . rev_lookup . find_local ( deref_chain. first ( ) . unwrap_or ( & place) . local ) ; 
105+         let  mut  base = data. rev_lookup . find_local ( place. local ) ; 
108106
109107        // The move path index of the first union that we find. Once this is 
110108        // some we stop creating child move paths, since moves from unions 
@@ -113,55 +111,60 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
113111        // from `*(u.f: &_)` isn't allowed. 
114112        let  mut  union_path = None ; 
115113
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 ( ..)  => { 
123-                         return  Err ( MoveError :: cannot_move_out_of ( 
124-                             self . loc , 
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 ( _)  => { 
114+         for  ( place_ref,  elem)  in  data. rev_lookup . un_derefer . iter_projections ( place. as_ref ( ) )  { 
115+             let  body = self . builder . body ; 
116+             let  tcx = self . builder . tcx ; 
117+             let  place_ty = place_ref. ty ( body,  tcx) . ty ; 
118+             match  place_ty. kind ( )  { 
119+                 ty:: Ref ( ..)  | ty:: RawPtr ( ..)  => { 
120+                     return  Err ( MoveError :: cannot_move_out_of ( 
121+                         self . loc , 
122+                         BorrowedContent  {  target_place :  place_ref. project_deeper ( & [ elem] ,  tcx)  } , 
123+                     ) ) ; 
124+                 } 
125+                 ty:: Adt ( adt,  _)  if  adt. has_dtor ( tcx)  && !adt. is_box ( )  => { 
126+                     return  Err ( MoveError :: cannot_move_out_of ( 
127+                         self . loc , 
128+                         InteriorOfTypeWithDestructor  {  container_ty :  place_ty } , 
129+                     ) ) ; 
130+                 } 
131+                 ty:: Adt ( adt,  _)  if  adt. is_union ( )  => { 
132+                     union_path. get_or_insert ( base) ; 
133+                 } 
134+                 ty:: Slice ( _)  => { 
135+                     return  Err ( MoveError :: cannot_move_out_of ( 
136+                         self . loc , 
137+                         InteriorOfSliceOrArray  { 
138+                             ty :  place_ty, 
139+                             is_index :  matches ! ( elem,  ProjectionElem :: Index ( ..) ) , 
140+                         } , 
141+                     ) ) ; 
142+                 } 
143+ 
144+                 ty:: Array ( ..)  => { 
145+                     if  let  ProjectionElem :: Index ( ..)  = elem { 
140146                        return  Err ( MoveError :: cannot_move_out_of ( 
141147                            self . loc , 
142-                             InteriorOfSliceOrArray  { 
143-                                 ty :  place_ty, 
144-                                 is_index :  matches ! ( elem,  ProjectionElem :: Index ( ..) ) , 
145-                             } , 
148+                             InteriorOfSliceOrArray  {  ty :  place_ty,  is_index :  true  } , 
146149                        ) ) ; 
147150                    } 
151+                 } 
148152
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-                 } ; 
153+                 _ => { } 
154+             } ; 
160155
161-                 if  union_path. is_none ( )  { 
162-                     base = self 
163-                         . add_move_path ( base,  elem,  |tcx| place_ref. project_deeper ( & [ elem] ,  tcx) ) ; 
164-                 } 
156+             if  union_path. is_none ( )  { 
157+                 // inlined from add_move_path because of a borrowck conflict with the iterator 
158+                 base =
159+                     * data. rev_lookup . projections . entry ( ( base,  elem. lift ( ) ) ) . or_insert_with ( || { 
160+                         MoveDataBuilder :: new_move_path ( 
161+                             & mut  data. move_paths , 
162+                             & mut  data. path_map , 
163+                             & mut  data. init_path_map , 
164+                             Some ( base) , 
165+                             place_ref. project_deeper ( & [ elem] ,  tcx) , 
166+                         ) 
167+                     } ) 
165168            } 
166169        } 
167170
@@ -282,10 +285,14 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
282285    fn  gather_statement ( & mut  self ,  stmt :  & Statement < ' tcx > )  { 
283286        match  & stmt. kind  { 
284287            StatementKind :: Assign ( box ( place,  Rvalue :: CopyForDeref ( reffed) ) )  => { 
285-                 assert ! ( place. projection. is_empty( ) ) ; 
286-                 if  self . builder . body . local_decls [ place. local ] . is_deref_temp ( )  { 
287-                     self . builder . data . rev_lookup . derefer_sidetable . insert ( place. local ,  * reffed) ; 
288-                 } 
288+                 let  local = place. as_local ( ) . unwrap ( ) ; 
289+                 assert ! ( self . builder. body. local_decls[ local] . is_deref_temp( ) ) ; 
290+ 
291+                 let  rev_lookup = & mut  self . builder . data . rev_lookup ; 
292+ 
293+                 rev_lookup. un_derefer . insert ( local,  reffed. as_ref ( ) ) ; 
294+                 let  base_local = rev_lookup. un_derefer . deref_chain ( local) . first ( ) . unwrap ( ) . local ; 
295+                 rev_lookup. locals [ local]  = rev_lookup. locals [ base_local] ; 
289296            } 
290297            StatementKind :: Assign ( box ( place,  rval) )  => { 
291298                self . create_move_path ( * place) ; 
@@ -306,7 +313,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
306313            StatementKind :: StorageLive ( _)  => { } 
307314            StatementKind :: StorageDead ( local)  => { 
308315                // DerefTemp locals (results of CopyForDeref) don't actually move anything. 
309-                 if  !self . builder . data . rev_lookup . derefer_sidetable . contains_key ( & local )  { 
316+                 if  !self . builder . body . local_decls [ * local ] . is_deref_temp ( )  { 
310317                    self . gather_move ( Place :: from ( * local) ) ; 
311318                } 
312319            } 
0 commit comments