@@ -7,6 +7,7 @@ use std::iter;
77
88use  hir_def:: { DefWithBodyId ,  HasModule } ; 
99use  la_arena:: ArenaMap ; 
10+ use  rustc_hash:: FxHashMap ; 
1011use  stdx:: never; 
1112use  triomphe:: Arc ; 
1213
@@ -33,11 +34,27 @@ pub struct MovedOutOfRef {
3334    pub  span :  MirSpan , 
3435} 
3536
37+ #[ derive( Debug ,  Clone ,  PartialEq ,  Eq ) ]  
38+ pub  struct  PartiallyMoved  { 
39+     pub  ty :  Ty , 
40+     pub  span :  MirSpan , 
41+     pub  local :  LocalId , 
42+ } 
43+ 
44+ #[ derive( Debug ,  Clone ,  PartialEq ,  Eq ) ]  
45+ pub  struct  BorrowRegion  { 
46+     pub  local :  LocalId , 
47+     pub  kind :  BorrowKind , 
48+     pub  places :  Vec < MirSpan > , 
49+ } 
50+ 
3651#[ derive( Debug ,  Clone ,  PartialEq ,  Eq ) ]  
3752pub  struct  BorrowckResult  { 
3853    pub  mir_body :  Arc < MirBody > , 
3954    pub  mutability_of_locals :  ArenaMap < LocalId ,  MutabilityReason > , 
4055    pub  moved_out_of_ref :  Vec < MovedOutOfRef > , 
56+     pub  partially_moved :  Vec < PartiallyMoved > , 
57+     pub  borrow_regions :  Vec < BorrowRegion > , 
4158} 
4259
4360fn  all_mir_bodies ( 
@@ -77,6 +94,8 @@ pub fn borrowck_query(
7794        res. push ( BorrowckResult  { 
7895            mutability_of_locals :  mutability_of_locals ( db,  & body) , 
7996            moved_out_of_ref :  moved_out_of_ref ( db,  & body) , 
97+             partially_moved :  partially_moved ( db,  & body) , 
98+             borrow_regions :  borrow_regions ( db,  & body) , 
8099            mir_body :  body, 
81100        } ) ; 
82101    } ) ?; 
@@ -185,6 +204,149 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
185204    result
186205} 
187206
207+ fn  partially_moved ( db :  & dyn  HirDatabase ,  body :  & MirBody )  -> Vec < PartiallyMoved >  { 
208+     let  mut  result = vec ! [ ] ; 
209+     let  mut  for_operand = |op :  & Operand ,  span :  MirSpan | match  op { 
210+         Operand :: Copy ( p)  | Operand :: Move ( p)  => { 
211+             let  mut  ty:  Ty  = body. locals [ p. local ] . ty . clone ( ) ; 
212+             for  proj in  p. projection . lookup ( & body. projection_store )  { 
213+                 ty = proj. projected_ty ( 
214+                     ty, 
215+                     db, 
216+                     |c,  subst,  f| { 
217+                         let  ( def,  _)  = db. lookup_intern_closure ( c. into ( ) ) ; 
218+                         let  infer = db. infer ( def) ; 
219+                         let  ( captures,  _)  = infer. closure_info ( & c) ; 
220+                         let  parent_subst = ClosureSubst ( subst) . parent_subst ( ) ; 
221+                         captures
222+                             . get ( f) 
223+                             . expect ( "broken closure field" ) 
224+                             . ty 
225+                             . clone ( ) 
226+                             . substitute ( Interner ,  parent_subst) 
227+                     } , 
228+                     body. owner . module ( db. upcast ( ) ) . krate ( ) , 
229+                 ) ; 
230+             } 
231+             if  !ty. clone ( ) . is_copy ( db,  body. owner ) 
232+                 && !ty. data ( Interner ) . flags . intersects ( TypeFlags :: HAS_ERROR ) 
233+             { 
234+                 result. push ( PartiallyMoved  {  span,  ty,  local :  p. local  } ) ; 
235+             } 
236+         } 
237+         Operand :: Constant ( _)  | Operand :: Static ( _)  => ( ) , 
238+     } ; 
239+     for  ( _,  block)  in  body. basic_blocks . iter ( )  { 
240+         db. unwind_if_cancelled ( ) ; 
241+         for  statement in  & block. statements  { 
242+             match  & statement. kind  { 
243+                 StatementKind :: Assign ( _,  r)  => match  r { 
244+                     Rvalue :: ShallowInitBoxWithAlloc ( _)  => ( ) , 
245+                     Rvalue :: ShallowInitBox ( o,  _) 
246+                     | Rvalue :: UnaryOp ( _,  o) 
247+                     | Rvalue :: Cast ( _,  o,  _) 
248+                     | Rvalue :: Repeat ( o,  _) 
249+                     | Rvalue :: Use ( o)  => for_operand ( o,  statement. span ) , 
250+                     Rvalue :: CopyForDeref ( _) 
251+                     | Rvalue :: Discriminant ( _) 
252+                     | Rvalue :: Len ( _) 
253+                     | Rvalue :: Ref ( _,  _)  => ( ) , 
254+                     Rvalue :: CheckedBinaryOp ( _,  o1,  o2)  => { 
255+                         for_operand ( o1,  statement. span ) ; 
256+                         for_operand ( o2,  statement. span ) ; 
257+                     } 
258+                     Rvalue :: Aggregate ( _,  ops)  => { 
259+                         for  op in  ops. iter ( )  { 
260+                             for_operand ( op,  statement. span ) ; 
261+                         } 
262+                     } 
263+                 } , 
264+                 StatementKind :: FakeRead ( _) 
265+                 | StatementKind :: Deinit ( _) 
266+                 | StatementKind :: StorageLive ( _) 
267+                 | StatementKind :: StorageDead ( _) 
268+                 | StatementKind :: Nop  => ( ) , 
269+             } 
270+         } 
271+         match  & block. terminator  { 
272+             Some ( terminator)  => match  & terminator. kind  { 
273+                 TerminatorKind :: SwitchInt  {  discr,  .. }  => for_operand ( discr,  terminator. span ) , 
274+                 TerminatorKind :: FalseEdge  {  .. } 
275+                 | TerminatorKind :: FalseUnwind  {  .. } 
276+                 | TerminatorKind :: Goto  {  .. } 
277+                 | TerminatorKind :: UnwindResume 
278+                 | TerminatorKind :: GeneratorDrop 
279+                 | TerminatorKind :: Abort 
280+                 | TerminatorKind :: Return 
281+                 | TerminatorKind :: Unreachable 
282+                 | TerminatorKind :: Drop  {  .. }  => ( ) , 
283+                 TerminatorKind :: DropAndReplace  {  value,  .. }  => { 
284+                     for_operand ( value,  terminator. span ) ; 
285+                 } 
286+                 TerminatorKind :: Call  {  func,  args,  .. }  => { 
287+                     for_operand ( func,  terminator. span ) ; 
288+                     args. iter ( ) . for_each ( |it| for_operand ( it,  terminator. span ) ) ; 
289+                 } 
290+                 TerminatorKind :: Assert  {  cond,  .. }  => { 
291+                     for_operand ( cond,  terminator. span ) ; 
292+                 } 
293+                 TerminatorKind :: Yield  {  value,  .. }  => { 
294+                     for_operand ( value,  terminator. span ) ; 
295+                 } 
296+             } , 
297+             None  => ( ) , 
298+         } 
299+     } 
300+     result. shrink_to_fit ( ) ; 
301+     result
302+ } 
303+ 
304+ fn  borrow_regions ( db :  & dyn  HirDatabase ,  body :  & MirBody )  -> Vec < BorrowRegion >  { 
305+     let  mut  borrows = FxHashMap :: default ( ) ; 
306+     for  ( _,  block)  in  body. basic_blocks . iter ( )  { 
307+         db. unwind_if_cancelled ( ) ; 
308+         for  statement in  & block. statements  { 
309+             match  & statement. kind  { 
310+                 StatementKind :: Assign ( _,  r)  => match  r { 
311+                     Rvalue :: Ref ( kind,  p)  => { 
312+                         borrows
313+                             . entry ( p. local ) 
314+                             . and_modify ( |it :  & mut  BorrowRegion | { 
315+                                 it. places . push ( statement. span ) ; 
316+                             } ) 
317+                             . or_insert_with ( || BorrowRegion  { 
318+                                 local :  p. local , 
319+                                 kind :  * kind, 
320+                                 places :  vec ! [ statement. span] , 
321+                             } ) ; 
322+                     } 
323+                     _ => ( ) , 
324+                 } , 
325+                 _ => ( ) , 
326+             } 
327+         } 
328+         match  & block. terminator  { 
329+             Some ( terminator)  => match  & terminator. kind  { 
330+                 TerminatorKind :: FalseEdge  {  .. } 
331+                 | TerminatorKind :: FalseUnwind  {  .. } 
332+                 | TerminatorKind :: Goto  {  .. } 
333+                 | TerminatorKind :: UnwindResume 
334+                 | TerminatorKind :: GeneratorDrop 
335+                 | TerminatorKind :: Abort 
336+                 | TerminatorKind :: Return 
337+                 | TerminatorKind :: Unreachable 
338+                 | TerminatorKind :: Drop  {  .. }  => ( ) , 
339+                 TerminatorKind :: DropAndReplace  {  .. }  => { } 
340+                 TerminatorKind :: Call  {  .. }  => { } 
341+                 _ => ( ) , 
342+             } , 
343+             None  => ( ) , 
344+         } 
345+     } 
346+ 
347+     borrows. into_values ( ) . collect ( ) 
348+ } 
349+ 
188350#[ derive( Debug ,  Clone ,  Copy ,  PartialEq ,  Eq ) ]  
189351enum  ProjectionCase  { 
190352    /// Projection is a local 
0 commit comments