@@ -4,7 +4,6 @@ use rustc_middle::mir::*;
4
4
use rustc_middle:: ty:: { self , TyCtxt } ;
5
5
use smallvec:: { smallvec, SmallVec } ;
6
6
7
- use std:: iter;
8
7
use std:: mem;
9
8
10
9
use super :: abs_domain:: Lift ;
@@ -40,22 +39,22 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
40
39
locals : body
41
40
. local_decls
42
41
. 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 {
47
46
Self :: new_move_path (
48
47
& mut move_paths,
49
48
& mut path_map,
50
49
& mut init_path_map,
51
50
None ,
52
51
Place :: from ( i) ,
53
- ) ,
54
- )
52
+ )
53
+ }
55
54
} )
56
55
. collect ( ) ,
57
56
projections : Default :: default ( ) ,
58
- derefer_sidetable : Default :: default ( ) ,
57
+ un_derefer : Default :: default ( ) ,
59
58
} ,
60
59
move_paths,
61
60
path_map,
@@ -100,11 +99,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
100
99
///
101
100
/// Maybe we should have separate "borrowck" and "moveck" modes.
102
101
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 ;
104
103
105
104
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 ) ;
108
106
109
107
// The move path index of the first union that we find. Once this is
110
108
// some we stop creating child move paths, since moves from unions
@@ -113,55 +111,60 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
113
111
// from `*(u.f: &_)` isn't allowed.
114
112
let mut union_path = None ;
115
113
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 {
140
146
return Err ( MoveError :: cannot_move_out_of (
141
147
self . loc ,
142
- InteriorOfSliceOrArray {
143
- ty : place_ty,
144
- is_index : matches ! ( elem, ProjectionElem :: Index ( ..) ) ,
145
- } ,
148
+ InteriorOfSliceOrArray { ty : place_ty, is_index : true } ,
146
149
) ) ;
147
150
}
151
+ }
148
152
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
+ } ;
160
155
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
+ } )
165
168
}
166
169
}
167
170
@@ -282,10 +285,14 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
282
285
fn gather_statement ( & mut self , stmt : & Statement < ' tcx > ) {
283
286
match & stmt. kind {
284
287
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] ;
289
296
}
290
297
StatementKind :: Assign ( box ( place, rval) ) => {
291
298
self . create_move_path ( * place) ;
@@ -306,7 +313,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
306
313
StatementKind :: StorageLive ( _) => { }
307
314
StatementKind :: StorageDead ( local) => {
308
315
// 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 ( ) {
310
317
self . gather_move ( Place :: from ( * local) ) ;
311
318
}
312
319
}
0 commit comments