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
///
@@ -211,11 +229,15 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
211
229
// So it's safe to skip these.
212
230
ProjectionElem :: OpaqueCast ( _) | ProjectionElem :: Downcast ( _, _) => ( ) ,
213
231
}
232
+ let elem_ty = PlaceTy :: from_ty ( place_ty) . projection_ty ( tcx, elem) . ty ;
233
+ if !( self . builder . filter ) ( elem_ty) {
234
+ return MovePathResult :: Error ;
235
+ }
214
236
if union_path. is_none ( ) {
215
237
// inlined from add_move_path because of a borrowck conflict with the iterator
216
238
base =
217
239
* data. rev_lookup . projections . entry ( ( base, elem. lift ( ) ) ) . or_insert_with ( || {
218
- MoveDataBuilder :: new_move_path (
240
+ new_move_path (
219
241
& mut data. move_paths ,
220
242
& mut data. path_map ,
221
243
& mut data. init_path_map ,
@@ -246,13 +268,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
246
268
..
247
269
} = self . builder ;
248
270
* rev_lookup. projections . entry ( ( base, elem. lift ( ) ) ) . or_insert_with ( move || {
249
- MoveDataBuilder :: new_move_path (
250
- move_paths,
251
- path_map,
252
- init_path_map,
253
- Some ( base) ,
254
- mk_place ( * tcx) ,
255
- )
271
+ new_move_path ( move_paths, path_map, init_path_map, Some ( base) , mk_place ( * tcx) )
256
272
} )
257
273
}
258
274
@@ -263,7 +279,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
263
279
}
264
280
}
265
281
266
- impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
282
+ impl < ' a , ' tcx , F > MoveDataBuilder < ' a , ' tcx , F > {
267
283
fn finalize ( self ) -> MoveData < ' tcx > {
268
284
debug ! ( "{}" , {
269
285
debug!( "moves for {:?}:" , self . body. span) ;
@@ -285,8 +301,9 @@ pub(super) fn gather_moves<'tcx>(
285
301
body : & Body < ' tcx > ,
286
302
tcx : TyCtxt < ' tcx > ,
287
303
param_env : ty:: ParamEnv < ' tcx > ,
304
+ filter : impl Fn ( Ty < ' tcx > ) -> bool ,
288
305
) -> MoveData < ' tcx > {
289
- let mut builder = MoveDataBuilder :: new ( body, tcx, param_env) ;
306
+ let mut builder = MoveDataBuilder :: new ( body, tcx, param_env, filter ) ;
290
307
291
308
builder. gather_args ( ) ;
292
309
@@ -303,7 +320,10 @@ pub(super) fn gather_moves<'tcx>(
303
320
builder. finalize ( )
304
321
}
305
322
306
- impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
323
+ impl < ' a , ' tcx , F > MoveDataBuilder < ' a , ' tcx , F >
324
+ where
325
+ F : Fn ( Ty < ' tcx > ) -> bool ,
326
+ {
307
327
fn gather_args ( & mut self ) {
308
328
for arg in self . body . args_iter ( ) {
309
329
if let Some ( path) = self . data . rev_lookup . find_local ( arg) {
@@ -331,12 +351,15 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
331
351
}
332
352
}
333
353
334
- struct Gatherer < ' b , ' a , ' tcx > {
335
- builder : & ' b mut MoveDataBuilder < ' a , ' tcx > ,
354
+ struct Gatherer < ' b , ' a , ' tcx , F > {
355
+ builder : & ' b mut MoveDataBuilder < ' a , ' tcx , F > ,
336
356
loc : Location ,
337
357
}
338
358
339
- impl < ' b , ' a , ' tcx > Gatherer < ' b , ' a , ' tcx > {
359
+ impl < ' b , ' a , ' tcx , F > Gatherer < ' b , ' a , ' tcx , F >
360
+ where
361
+ F : Fn ( Ty < ' tcx > ) -> bool ,
362
+ {
340
363
fn gather_statement ( & mut self , stmt : & Statement < ' tcx > ) {
341
364
match & stmt. kind {
342
365
StatementKind :: Assign ( box ( place, Rvalue :: CopyForDeref ( reffed) ) ) => {
0 commit comments