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 ///
@@ -214,11 +232,15 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
214232 | ProjectionElem :: Subtype ( _)
215233 | ProjectionElem :: Downcast ( _, _) => ( ) ,
216234 }
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+ }
217239 if union_path. is_none ( ) {
218240 // inlined from add_move_path because of a borrowck conflict with the iterator
219241 base =
220242 * data. rev_lookup . projections . entry ( ( base, elem. lift ( ) ) ) . or_insert_with ( || {
221- MoveDataBuilder :: new_move_path (
243+ new_move_path (
222244 & mut data. move_paths ,
223245 & mut data. path_map ,
224246 & mut data. init_path_map ,
@@ -249,13 +271,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
249271 ..
250272 } = self . builder ;
251273 * 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) )
259275 } )
260276 }
261277
@@ -266,7 +282,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
266282 }
267283}
268284
269- impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
285+ impl < ' a , ' tcx , F > MoveDataBuilder < ' a , ' tcx , F > {
270286 fn finalize ( self ) -> MoveData < ' tcx > {
271287 debug ! ( "{}" , {
272288 debug!( "moves for {:?}:" , self . body. span) ;
@@ -288,8 +304,9 @@ pub(super) fn gather_moves<'tcx>(
288304 body : & Body < ' tcx > ,
289305 tcx : TyCtxt < ' tcx > ,
290306 param_env : ty:: ParamEnv < ' tcx > ,
307+ filter : impl Fn ( Ty < ' tcx > ) -> bool ,
291308) -> MoveData < ' tcx > {
292- let mut builder = MoveDataBuilder :: new ( body, tcx, param_env) ;
309+ let mut builder = MoveDataBuilder :: new ( body, tcx, param_env, filter ) ;
293310
294311 builder. gather_args ( ) ;
295312
@@ -306,7 +323,10 @@ pub(super) fn gather_moves<'tcx>(
306323 builder. finalize ( )
307324}
308325
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+ {
310330 fn gather_args ( & mut self ) {
311331 for arg in self . body . args_iter ( ) {
312332 if let Some ( path) = self . data . rev_lookup . find_local ( arg) {
@@ -334,12 +354,15 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
334354 }
335355}
336356
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 > ,
339359 loc : Location ,
340360}
341361
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+ {
343366 fn gather_statement ( & mut self , stmt : & Statement < ' tcx > ) {
344367 match & stmt. kind {
345368 StatementKind :: Assign ( box ( place, Rvalue :: CopyForDeref ( reffed) ) ) => {
0 commit comments