@@ -128,9 +128,8 @@ use rustc_data_structures::graph::implementation::{Graph, NodeIndex};
128128use rustc_middle:: mir:: visit:: PlaceContext ;
129129use rustc_middle:: mir:: visit:: Visitor ;
130130use rustc_middle:: mir:: * ;
131- use rustc_middle:: ty:: { self , Ty , TypeSuperVisitable , TypeVisitable } ;
131+ use rustc_middle:: ty;
132132
133- use core:: ops:: ControlFlow ;
134133use either:: Either ;
135134
136135#[ derive( Copy , Clone , Debug ) ]
@@ -158,43 +157,6 @@ impl NodeKind {
158157 }
159158}
160159
161- /// TypeVisitor that looks for `ty::Ref`, `ty::RawPtr`. Additionally looks for `ty::Param`,
162- /// which could themselves refer to references or raw pointers.
163- struct MaybeHasRefsOrPointersVisitor {
164- has_refs_or_pointers : bool ,
165- has_params : bool ,
166- }
167-
168- impl MaybeHasRefsOrPointersVisitor {
169- fn new ( ) -> Self {
170- MaybeHasRefsOrPointersVisitor { has_refs_or_pointers : false , has_params : false }
171- }
172- }
173-
174- impl < ' tcx > ty:: TypeVisitor < TyCtxt < ' tcx > > for MaybeHasRefsOrPointersVisitor {
175- type BreakTy = ( ) ;
176-
177- #[ instrument( skip( self ) , level = "debug" ) ]
178- fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
179- match ty. kind ( ) {
180- ty:: Ref ( ..) => {
181- self . has_refs_or_pointers = true ;
182- return ControlFlow :: Break ( ( ) ) ;
183- }
184- ty:: RawPtr ( ..) => {
185- self . has_refs_or_pointers = true ;
186- return ControlFlow :: Break ( ( ) ) ;
187- }
188- ty:: Param ( _) => {
189- self . has_params = true ;
190- }
191- _ => { }
192- }
193-
194- ty. super_visit_with ( self )
195- }
196- }
197-
198160/// Used to build a dependency graph between borrows/pointers and the `Local`s that
199161/// they reference.
200162/// We add edges to the graph in two kinds of situations:
@@ -265,6 +227,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowDependencies<'a, 'tcx> {
265227 match & statement. kind {
266228 StatementKind :: Assign ( assign) => {
267229 let assign_place = assign. 0 ;
230+ debug ! ( "assign_place_ty: {:?}" , assign_place. ty( self . local_decls, self . tcx) . ty) ;
268231 let assign_local = assign_place. local ;
269232 self . current_local = Some ( assign_local) ;
270233 debug ! ( "set current_local to {:?}" , self . current_local) ;
@@ -305,12 +268,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowDependencies<'a, 'tcx> {
305268 let src_node_kind = NodeKind :: Borrow ( src_local) ;
306269 let src_node_idx = self . maybe_create_node ( src_node_kind) ;
307270
308- let node_idx = if let Some ( node_idx) = self . locals_to_node_indexes . get ( & place. local )
309- {
310- * node_idx
311- } else {
312- bug ! ( "should have added a node for the moved borrowed place before" ) ;
313- } ;
271+ let node_kind = NodeKind :: Borrow ( place. local ) ;
272+ let node_idx = self . maybe_create_node ( node_kind) ;
314273
315274 debug ! (
316275 "adding edge from {:?}({:?}) -> {:?}({:?})" ,
@@ -346,10 +305,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowDependencies<'a, 'tcx> {
346305
347306 self . dep_graph . add_edge ( src_node_idx, node_idx, ( ) ) ;
348307 }
349- _ => {
350- // FIXME Need to also create edges for `Local`s that correspond to `NodeKind::LocalWithRefs` here
308+ Rvalue :: Cast ( ..) => {
309+ // FIXME we probably should handle pointer casts here directly
310+
351311 self . super_rvalue ( rvalue, location)
352312 }
313+ _ => self . super_rvalue ( rvalue, location) ,
353314 }
354315 }
355316
@@ -385,7 +346,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowDependencies<'a, 'tcx> {
385346 None => { }
386347 } ,
387348 _ => {
388- // FIXME Need to also create edges for `Local`s that correspond to `NodeKind::LocalWithRefs` here
349+ // FIXME I think we probably need to introduce edges here if `place.local`
350+ // corresponds to a `NodeKind::LocalWithRefs`
389351 }
390352 }
391353
@@ -404,26 +366,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowDependencies<'a, 'tcx> {
404366 let dest_ty = destination. ty ( self . local_decls , self . tcx ) . ty ;
405367 debug ! ( ?dest_ty) ;
406368
407- let mut has_refs_or_pointers_visitor = MaybeHasRefsOrPointersVisitor :: new ( ) ;
408- dest_ty. visit_with ( & mut has_refs_or_pointers_visitor) ;
409-
410- let dest_might_include_refs_or_pointers =
411- if has_refs_or_pointers_visitor. has_refs_or_pointers {
412- true
413- } else if has_refs_or_pointers_visitor. has_params {
414- // if we pass in any references or raw pointers as arguments and the
415- // return type includes type parameters, these type parameters could
416- // refer to those refs/ptrs, so we have to be conservative here and possibly
417- // include an edge.
418- true
419- } else {
420- false
421- } ;
422-
423- if dest_might_include_refs_or_pointers {
424- self . current_local = Some ( destination. local ) ;
425- debug ! ( "self.current_local: {:?}" , self . current_local) ;
426- }
369+ // To ensure safety we need to add `destination` to the graph as a `Node` with `NodeKind::LocalWithRefs`
370+ // if we pass in any refs/ptrs or `Local`s corresponding to `NodeKind::LocalWithRefs`. The reason for this
371+ // is that the function could include those refs/ptrs in its return value. It's not sufficient
372+ // to look for the existence of `ty::Ref` or `ty::RawPtr` in the type of the return type, since the
373+ // function could also cast pointers to integers e.g. .
374+ self . current_local = Some ( destination. local ) ;
427375
428376 self . visit_operand ( func, location) ;
429377 for arg in args {
@@ -436,26 +384,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowDependencies<'a, 'tcx> {
436384 let resume_arg_ty = resume_arg. ty ( self . local_decls , self . tcx ) . ty ;
437385 debug ! ( ?resume_arg_ty) ;
438386
439- let mut has_refs_or_pointers_visitor = MaybeHasRefsOrPointersVisitor :: new ( ) ;
440- resume_arg_ty. visit_with ( & mut has_refs_or_pointers_visitor) ;
441-
442- let dest_might_include_refs_or_pointers =
443- if has_refs_or_pointers_visitor. has_refs_or_pointers {
444- true
445- } else if has_refs_or_pointers_visitor. has_params {
446- // if we pass in any references or raw pointers as arguments and the
447- // return type includes type parameters, these type parameters could
448- // refer to those refs/ptrs, so we have to be conservative here and possibly
449- // include an edge.
450- true
451- } else {
452- false
453- } ;
454-
455- if dest_might_include_refs_or_pointers {
456- self . current_local = Some ( resume_arg. local ) ;
457- debug ! ( "self.current_local: {:?}" , self . current_local) ;
458- }
387+ // We may need to add edges from `destination`, see the comment for this statement
388+ // in `TerminatorKind::Call` for the rationale behind this.
389+ self . current_local = Some ( resume_arg. local ) ;
459390
460391 self . super_operand ( value, location) ;
461392 }
@@ -578,6 +509,7 @@ pub fn get_borrowed_locals_results<'mir, 'tcx>(
578509 )
579510 }
580511 }
512+
581513 let live_borrows = LiveBorrows :: new ( body, tcx, borrow_deps) ;
582514 let results =
583515 live_borrows. into_engine ( tcx, body) . pass_name ( "borrowed_locals" ) . iterate_to_fixpoint ( ) ;
@@ -763,6 +695,15 @@ where
763695 self . visit_rvalue ( & assign. 1 , location) ;
764696 }
765697 _ => {
698+ if let Some ( node_idx) =
699+ self . borrow_deps . locals_to_node_indexes . get ( & lhs_place. local )
700+ {
701+ let node = self . borrow_deps . dep_graph . node ( * node_idx) ;
702+ if let NodeKind :: LocalWithRefs ( _) = node. data {
703+ debug ! ( "killing {:?}" , lhs_place. local) ;
704+ self . _trans . kill ( lhs_place. local ) ;
705+ }
706+ }
766707 self . super_assign ( & assign. 0 , & assign. 1 , location) ;
767708 }
768709 }
@@ -828,18 +769,32 @@ where
828769
829770 #[ instrument( skip( self ) , level = "debug" ) ]
830771 fn visit_terminator ( & mut self , terminator : & mir:: Terminator < ' tcx > , location : Location ) {
831- match terminator. kind {
832- TerminatorKind :: Call { destination, .. } => {
833- debug ! ( "killing {:?}" , destination. local) ;
834- self . _trans . kill ( destination. local ) ;
772+ match & terminator. kind {
773+ TerminatorKind :: Call { destination, args, .. } => {
774+ match destination. projection . as_slice ( ) {
775+ & [ ] | & [ ProjectionElem :: OpaqueCast ( _) ] => {
776+ debug ! ( "killing {:?}" , destination. local) ;
777+ self . _trans . kill ( destination. local ) ;
778+
779+ for arg in args {
780+ self . visit_operand ( arg, location)
781+ }
782+ }
783+ _ => self . super_terminator ( terminator, location) ,
784+ }
835785 }
836- TerminatorKind :: Yield { resume_arg, .. } => {
837- debug ! ( "killing {:?}" , resume_arg. local) ;
838- self . _trans . kill ( resume_arg. local ) ;
786+ TerminatorKind :: Yield { resume_arg, value, .. } => {
787+ match resume_arg. projection . as_slice ( ) {
788+ & [ ] | & [ ProjectionElem :: OpaqueCast ( _) ] => {
789+ debug ! ( "killing {:?}" , resume_arg. local) ;
790+ self . _trans . kill ( resume_arg. local ) ;
791+
792+ self . visit_operand ( value, location)
793+ }
794+ _ => self . super_terminator ( terminator, location) ,
795+ }
839796 }
840- _ => { }
797+ _ => self . super_terminator ( terminator , location ) ,
841798 }
842-
843- self . super_terminator ( terminator, location) ;
844799 }
845800}
0 commit comments