@@ -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.
102101 fn 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