1
- use crate :: move_paths:: FxHashMap ;
2
- use crate :: un_derefer:: UnDerefer ;
3
1
use rustc_index:: IndexVec ;
4
2
use rustc_middle:: mir:: tcx:: RvalueInitializationState ;
5
3
use rustc_middle:: mir:: * ;
6
4
use rustc_middle:: ty:: { self , TyCtxt } ;
7
5
use smallvec:: { smallvec, SmallVec } ;
8
6
7
+ use std:: iter;
9
8
use std:: mem;
10
9
11
10
use super :: abs_domain:: Lift ;
@@ -21,7 +20,6 @@ struct MoveDataBuilder<'a, 'tcx> {
21
20
param_env : ty:: ParamEnv < ' tcx > ,
22
21
data : MoveData < ' tcx > ,
23
22
errors : Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > ,
24
- un_derefer : UnDerefer < ' tcx > ,
25
23
}
26
24
27
25
impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
@@ -35,25 +33,29 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
35
33
tcx,
36
34
param_env,
37
35
errors : Vec :: new ( ) ,
38
- un_derefer : UnDerefer { tcx : tcx, derefer_sidetable : Default :: default ( ) } ,
39
36
data : MoveData {
40
37
moves : IndexVec :: new ( ) ,
41
38
loc_map : LocationMap :: new ( body) ,
42
39
rev_lookup : MovePathLookup {
43
40
locals : body
44
41
. 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
+ ) ,
53
54
)
54
55
} )
55
56
. collect ( ) ,
56
57
projections : Default :: default ( ) ,
58
+ derefer_sidetable : Default :: default ( ) ,
57
59
} ,
58
60
move_paths,
59
61
path_map,
@@ -98,13 +100,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
98
100
///
99
101
/// Maybe we should have separate "borrowck" and "moveck" modes.
100
102
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 ( ) ) ;
105
104
106
105
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 ) ;
108
108
109
109
// The move path index of the first union that we find. Once this is
110
110
// some we stop creating child move paths, since moves from unions
@@ -113,51 +113,55 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
113
113
// from `*(u.f: &_)` isn't allowed.
114
114
let mut union_path = None ;
115
115
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 ( ..) => {
149
123
return Err ( MoveError :: cannot_move_out_of (
150
124
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
+ } ,
152
146
) ) ;
153
147
}
154
- }
155
148
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
+ } ;
158
160
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
+ }
161
165
}
162
166
}
163
167
@@ -198,10 +202,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
198
202
}
199
203
}
200
204
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 > ) > ) > ;
205
207
206
208
impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
207
209
fn finalize ( self ) -> MoveDat < ' tcx > {
@@ -217,11 +219,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
217
219
"done dumping moves"
218
220
} ) ;
219
221
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 ) ) }
225
223
}
226
224
}
227
225
@@ -250,7 +248,7 @@ pub(super) fn gather_moves<'tcx>(
250
248
impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
251
249
fn gather_args ( & mut self ) {
252
250
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) ;
254
252
255
253
let init = self . data . inits . push ( Init {
256
254
path,
@@ -286,7 +284,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
286
284
StatementKind :: Assign ( box ( place, Rvalue :: CopyForDeref ( reffed) ) ) => {
287
285
assert ! ( place. projection. is_empty( ) ) ;
288
286
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) ;
290
288
}
291
289
}
292
290
StatementKind :: Assign ( box ( place, rval) ) => {
@@ -308,7 +306,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
308
306
StatementKind :: StorageLive ( _) => { }
309
307
StatementKind :: StorageDead ( local) => {
310
308
// 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) {
312
310
self . gather_move ( Place :: from ( * local) ) ;
313
311
}
314
312
}
@@ -450,12 +448,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
450
448
451
449
fn gather_move ( & mut self , place : Place < ' tcx > ) {
452
450
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
-
459
451
if let [ ref base @ .., ProjectionElem :: Subslice { from, to, from_end : false } ] =
460
452
* * place. projection
461
453
{
@@ -512,11 +504,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
512
504
fn gather_init ( & mut self , place : PlaceRef < ' tcx > , kind : InitKind ) {
513
505
debug ! ( "gather_init({:?}, {:?})" , self . loc, place) ;
514
506
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
-
520
507
let mut place = place;
521
508
522
509
// Check if we are assigning into a field of a union, if so, lookup the place
0 commit comments