11use rustc_index:: IndexVec ;
2- use rustc_middle:: mir:: tcx:: RvalueInitializationState ;
2+ use rustc_middle:: mir:: tcx:: { PlaceTy , RvalueInitializationState } ;
33use rustc_middle:: mir:: * ;
4- use rustc_middle:: ty:: { self , TyCtxt } ;
4+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
55use smallvec:: { smallvec, SmallVec } ;
66
77use std:: mem;
@@ -12,19 +12,49 @@ use super::{
1212 LocationMap , MoveData , MoveOut , MoveOutIndex , MovePath , MovePathIndex , MovePathLookup ,
1313} ;
1414
15- struct MoveDataBuilder < ' a , ' tcx > {
15+ struct MoveDataBuilder < ' a , ' tcx , F > {
1616 body : & ' a Body < ' tcx > ,
1717 tcx : TyCtxt < ' tcx > ,
1818 param_env : ty:: ParamEnv < ' tcx > ,
1919 data : MoveData < ' tcx > ,
20+ filter : F ,
2021}
2122
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 {
2433 let mut move_paths = IndexVec :: new ( ) ;
2534 let mut path_map = IndexVec :: new ( ) ;
2635 let mut init_path_map = IndexVec :: new ( ) ;
2736
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+
2858 MoveDataBuilder {
2959 body,
3060 tcx,
@@ -33,23 +63,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
3363 moves : IndexVec :: new ( ) ,
3464 loc_map : LocationMap :: new ( body) ,
3565 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,
5367 projections : Default :: default ( ) ,
5468 un_derefer : Default :: default ( ) ,
5569 } ,
@@ -59,32 +73,33 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
5973 init_loc_map : LocationMap :: new ( body) ,
6074 init_path_map,
6175 } ,
76+ filter,
6277 }
6378 }
79+ }
6480
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+ }
7995
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) ;
8298
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) ;
85101
86- move_path
87- }
102+ move_path
88103}
89104
90105enum MovePathResult {
@@ -93,7 +108,10 @@ enum MovePathResult {
93108 Error ,
94109}
95110
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+ {
97115 /// This creates a MovePath for a given place, returning an `MovePathError`
98116 /// if that place can't be moved from.
99117 ///
@@ -211,11 +229,15 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
211229 // So it's safe to skip these.
212230 ProjectionElem :: OpaqueCast ( _) | ProjectionElem :: Downcast ( _, _) => ( ) ,
213231 }
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+ }
214236 if union_path. is_none ( ) {
215237 // inlined from add_move_path because of a borrowck conflict with the iterator
216238 base =
217239 * data. rev_lookup . projections . entry ( ( base, elem. lift ( ) ) ) . or_insert_with ( || {
218- MoveDataBuilder :: new_move_path (
240+ new_move_path (
219241 & mut data. move_paths ,
220242 & mut data. path_map ,
221243 & mut data. init_path_map ,
@@ -246,13 +268,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
246268 ..
247269 } = self . builder ;
248270 * 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) )
256272 } )
257273 }
258274
@@ -263,7 +279,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
263279 }
264280}
265281
266- impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
282+ impl < ' a , ' tcx , F > MoveDataBuilder < ' a , ' tcx , F > {
267283 fn finalize ( self ) -> MoveData < ' tcx > {
268284 debug ! ( "{}" , {
269285 debug!( "moves for {:?}:" , self . body. span) ;
@@ -285,8 +301,9 @@ pub(super) fn gather_moves<'tcx>(
285301 body : & Body < ' tcx > ,
286302 tcx : TyCtxt < ' tcx > ,
287303 param_env : ty:: ParamEnv < ' tcx > ,
304+ filter : impl Fn ( Ty < ' tcx > ) -> bool ,
288305) -> MoveData < ' tcx > {
289- let mut builder = MoveDataBuilder :: new ( body, tcx, param_env) ;
306+ let mut builder = MoveDataBuilder :: new ( body, tcx, param_env, filter ) ;
290307
291308 builder. gather_args ( ) ;
292309
@@ -303,7 +320,10 @@ pub(super) fn gather_moves<'tcx>(
303320 builder. finalize ( )
304321}
305322
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+ {
307327 fn gather_args ( & mut self ) {
308328 for arg in self . body . args_iter ( ) {
309329 if let Some ( path) = self . data . rev_lookup . find_local ( arg) {
@@ -331,12 +351,15 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
331351 }
332352}
333353
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 > ,
336356 loc : Location ,
337357}
338358
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+ {
340363 fn gather_statement ( & mut self , stmt : & Statement < ' tcx > ) {
341364 match & stmt. kind {
342365 StatementKind :: Assign ( box ( place, Rvalue :: CopyForDeref ( reffed) ) ) => {
0 commit comments