1
1
use rustc_index:: IndexVec ;
2
- use rustc_middle:: mir:: tcx:: RvalueInitializationState ;
2
+ use rustc_middle:: mir:: tcx:: { PlaceTy , RvalueInitializationState } ;
3
3
use rustc_middle:: mir:: * ;
4
- use rustc_middle:: ty:: { self , TyCtxt } ;
4
+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
5
5
use smallvec:: { smallvec, SmallVec } ;
6
6
7
7
use std:: mem;
@@ -12,19 +12,49 @@ use super::{
12
12
LocationMap , MoveData , MoveOut , MoveOutIndex , MovePath , MovePathIndex , MovePathLookup ,
13
13
} ;
14
14
15
- struct MoveDataBuilder < ' a , ' tcx > {
15
+ struct MoveDataBuilder < ' a , ' tcx , F > {
16
16
body : & ' a Body < ' tcx > ,
17
17
tcx : TyCtxt < ' tcx > ,
18
18
param_env : ty:: ParamEnv < ' tcx > ,
19
19
data : MoveData < ' tcx > ,
20
+ filter : F ,
20
21
}
21
22
22
- impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
23
- fn new ( body : & ' a Body < ' tcx > , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> Self {
23
+ impl < ' a , ' tcx , F > MoveDataBuilder < ' a , ' tcx , F >
24
+ where
25
+ F : Fn ( Ty < ' tcx > ) -> bool ,
26
+ {
27
+ fn new (
28
+ body : & ' a Body < ' tcx > ,
29
+ tcx : TyCtxt < ' tcx > ,
30
+ param_env : ty:: ParamEnv < ' tcx > ,
31
+ filter : F ,
32
+ ) -> Self {
24
33
let mut move_paths = IndexVec :: new ( ) ;
25
34
let mut path_map = IndexVec :: new ( ) ;
26
35
let mut init_path_map = IndexVec :: new ( ) ;
27
36
37
+ let locals = body
38
+ . local_decls
39
+ . iter_enumerated ( )
40
+ . map ( |( i, l) | {
41
+ if l. is_deref_temp ( ) {
42
+ return None ;
43
+ }
44
+ if filter ( l. ty ) {
45
+ Some ( new_move_path (
46
+ & mut move_paths,
47
+ & mut path_map,
48
+ & mut init_path_map,
49
+ None ,
50
+ Place :: from ( i) ,
51
+ ) )
52
+ } else {
53
+ None
54
+ }
55
+ } )
56
+ . collect ( ) ;
57
+
28
58
MoveDataBuilder {
29
59
body,
30
60
tcx,
@@ -33,23 +63,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
33
63
moves : IndexVec :: new ( ) ,
34
64
loc_map : LocationMap :: new ( body) ,
35
65
rev_lookup : MovePathLookup {
36
- locals : body
37
- . local_decls
38
- . iter_enumerated ( )
39
- . map ( |( i, l) | {
40
- if l. is_deref_temp ( ) {
41
- None
42
- } else {
43
- Some ( Self :: new_move_path (
44
- & mut move_paths,
45
- & mut path_map,
46
- & mut init_path_map,
47
- None ,
48
- Place :: from ( i) ,
49
- ) )
50
- }
51
- } )
52
- . collect ( ) ,
66
+ locals,
53
67
projections : Default :: default ( ) ,
54
68
un_derefer : Default :: default ( ) ,
55
69
} ,
@@ -59,32 +73,33 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
59
73
init_loc_map : LocationMap :: new ( body) ,
60
74
init_path_map,
61
75
} ,
76
+ filter,
62
77
}
63
78
}
79
+ }
64
80
65
- fn new_move_path (
66
- move_paths : & mut IndexVec < MovePathIndex , MovePath < ' tcx > > ,
67
- path_map : & mut IndexVec < MovePathIndex , SmallVec < [ MoveOutIndex ; 4 ] > > ,
68
- init_path_map : & mut IndexVec < MovePathIndex , SmallVec < [ InitIndex ; 4 ] > > ,
69
- parent : Option < MovePathIndex > ,
70
- place : Place < ' tcx > ,
71
- ) -> MovePathIndex {
72
- let move_path =
73
- move_paths. push ( MovePath { next_sibling : None , first_child : None , parent, place } ) ;
74
-
75
- if let Some ( parent) = parent {
76
- let next_sibling = mem:: replace ( & mut move_paths[ parent] . first_child , Some ( move_path) ) ;
77
- move_paths[ move_path] . next_sibling = next_sibling;
78
- }
81
+ fn new_move_path < ' tcx > (
82
+ move_paths : & mut IndexVec < MovePathIndex , MovePath < ' tcx > > ,
83
+ path_map : & mut IndexVec < MovePathIndex , SmallVec < [ MoveOutIndex ; 4 ] > > ,
84
+ init_path_map : & mut IndexVec < MovePathIndex , SmallVec < [ InitIndex ; 4 ] > > ,
85
+ parent : Option < MovePathIndex > ,
86
+ place : Place < ' tcx > ,
87
+ ) -> MovePathIndex {
88
+ let move_path =
89
+ move_paths. push ( MovePath { next_sibling : None , first_child : None , parent, place } ) ;
90
+
91
+ if let Some ( parent) = parent {
92
+ let next_sibling = mem:: replace ( & mut move_paths[ parent] . first_child , Some ( move_path) ) ;
93
+ move_paths[ move_path] . next_sibling = next_sibling;
94
+ }
79
95
80
- let path_map_ent = path_map. push ( smallvec ! [ ] ) ;
81
- assert_eq ! ( path_map_ent, move_path) ;
96
+ let path_map_ent = path_map. push ( smallvec ! [ ] ) ;
97
+ assert_eq ! ( path_map_ent, move_path) ;
82
98
83
- let init_path_map_ent = init_path_map. push ( smallvec ! [ ] ) ;
84
- assert_eq ! ( init_path_map_ent, move_path) ;
99
+ let init_path_map_ent = init_path_map. push ( smallvec ! [ ] ) ;
100
+ assert_eq ! ( init_path_map_ent, move_path) ;
85
101
86
- move_path
87
- }
102
+ move_path
88
103
}
89
104
90
105
enum MovePathResult {
@@ -93,7 +108,10 @@ enum MovePathResult {
93
108
Error ,
94
109
}
95
110
96
- impl < ' b , ' a , ' tcx > Gatherer < ' b , ' a , ' tcx > {
111
+ impl < ' b , ' a , ' tcx , F > Gatherer < ' b , ' a , ' tcx , F >
112
+ where
113
+ F : Fn ( Ty < ' tcx > ) -> bool ,
114
+ {
97
115
/// This creates a MovePath for a given place, returning an `MovePathError`
98
116
/// if that place can't be moved from.
99
117
///
@@ -214,11 +232,15 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
214
232
| ProjectionElem :: Subtype ( _)
215
233
| ProjectionElem :: Downcast ( _, _) => ( ) ,
216
234
}
235
+ let elem_ty = PlaceTy :: from_ty ( place_ty) . projection_ty ( tcx, elem) . ty ;
236
+ if !( self . builder . filter ) ( elem_ty) {
237
+ return MovePathResult :: Error ;
238
+ }
217
239
if union_path. is_none ( ) {
218
240
// inlined from add_move_path because of a borrowck conflict with the iterator
219
241
base =
220
242
* data. rev_lookup . projections . entry ( ( base, elem. lift ( ) ) ) . or_insert_with ( || {
221
- MoveDataBuilder :: new_move_path (
243
+ new_move_path (
222
244
& mut data. move_paths ,
223
245
& mut data. path_map ,
224
246
& mut data. init_path_map ,
@@ -249,13 +271,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
249
271
..
250
272
} = self . builder ;
251
273
* rev_lookup. projections . entry ( ( base, elem. lift ( ) ) ) . or_insert_with ( move || {
252
- MoveDataBuilder :: new_move_path (
253
- move_paths,
254
- path_map,
255
- init_path_map,
256
- Some ( base) ,
257
- mk_place ( * tcx) ,
258
- )
274
+ new_move_path ( move_paths, path_map, init_path_map, Some ( base) , mk_place ( * tcx) )
259
275
} )
260
276
}
261
277
@@ -266,7 +282,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
266
282
}
267
283
}
268
284
269
- impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
285
+ impl < ' a , ' tcx , F > MoveDataBuilder < ' a , ' tcx , F > {
270
286
fn finalize ( self ) -> MoveData < ' tcx > {
271
287
debug ! ( "{}" , {
272
288
debug!( "moves for {:?}:" , self . body. span) ;
@@ -288,8 +304,9 @@ pub(super) fn gather_moves<'tcx>(
288
304
body : & Body < ' tcx > ,
289
305
tcx : TyCtxt < ' tcx > ,
290
306
param_env : ty:: ParamEnv < ' tcx > ,
307
+ filter : impl Fn ( Ty < ' tcx > ) -> bool ,
291
308
) -> MoveData < ' tcx > {
292
- let mut builder = MoveDataBuilder :: new ( body, tcx, param_env) ;
309
+ let mut builder = MoveDataBuilder :: new ( body, tcx, param_env, filter ) ;
293
310
294
311
builder. gather_args ( ) ;
295
312
@@ -306,7 +323,10 @@ pub(super) fn gather_moves<'tcx>(
306
323
builder. finalize ( )
307
324
}
308
325
309
- impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
326
+ impl < ' a , ' tcx , F > MoveDataBuilder < ' a , ' tcx , F >
327
+ where
328
+ F : Fn ( Ty < ' tcx > ) -> bool ,
329
+ {
310
330
fn gather_args ( & mut self ) {
311
331
for arg in self . body . args_iter ( ) {
312
332
if let Some ( path) = self . data . rev_lookup . find_local ( arg) {
@@ -334,12 +354,15 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
334
354
}
335
355
}
336
356
337
- struct Gatherer < ' b , ' a , ' tcx > {
338
- builder : & ' b mut MoveDataBuilder < ' a , ' tcx > ,
357
+ struct Gatherer < ' b , ' a , ' tcx , F > {
358
+ builder : & ' b mut MoveDataBuilder < ' a , ' tcx , F > ,
339
359
loc : Location ,
340
360
}
341
361
342
- impl < ' b , ' a , ' tcx > Gatherer < ' b , ' a , ' tcx > {
362
+ impl < ' b , ' a , ' tcx , F > Gatherer < ' b , ' a , ' tcx , F >
363
+ where
364
+ F : Fn ( Ty < ' tcx > ) -> bool ,
365
+ {
343
366
fn gather_statement ( & mut self , stmt : & Statement < ' tcx > ) {
344
367
match & stmt. kind {
345
368
StatementKind :: Assign ( box ( place, Rvalue :: CopyForDeref ( reffed) ) ) => {
0 commit comments