@@ -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 ;
@@ -55,7 +54,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
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,8 @@ 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
+ assert ! ( self . builder. body. local_decls[ place. local] . is_deref_temp( ) ) ;
289
+ self . builder . data . rev_lookup . un_derefer . insert ( place. as_local ( ) . unwrap ( ) , * reffed) ;
289
290
}
290
291
StatementKind :: Assign ( box ( place, rval) ) => {
291
292
self . create_move_path ( * place) ;
@@ -306,7 +307,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
306
307
StatementKind :: StorageLive ( _) => { }
307
308
StatementKind :: StorageDead ( local) => {
308
309
// DerefTemp locals (results of CopyForDeref) don't actually move anything.
309
- if !self . builder . data . rev_lookup . derefer_sidetable . contains_key ( & local ) {
310
+ if !self . builder . body . local_decls [ * local ] . is_deref_temp ( ) {
310
311
self . gather_move ( Place :: from ( * local) ) ;
311
312
}
312
313
}
0 commit comments