@@ -1967,7 +1967,7 @@ impl PartialPath {
19671967 & mut symbol_stack_postcondition,
19681968 & mut scope_stack_postcondition,
19691969 )
1970- . expect ( "" ) ;
1970+ . expect ( "lifting single nodes to partial paths should not fail " ) ;
19711971
19721972 PartialPath {
19731973 start_node : node,
@@ -2056,56 +2056,11 @@ impl PartialPath {
20562056 }
20572057
20582058 pub fn starts_at_endpoint ( & self , graph : & StackGraph ) -> bool {
2059- let node = & graph[ self . start_node ] ;
2060- node. is_endpoint ( )
2059+ graph[ self . start_node ] . is_endpoint ( )
20612060 }
20622061
20632062 pub fn ends_at_endpoint ( & self , graph : & StackGraph ) -> bool {
2064- let node = & graph[ self . end_node ] ;
2065- node. is_endpoint ( ) || node. is_jump_to ( )
2066- }
2067-
2068- #[ cfg( not( feature = "partial-path-finding-v1" ) ) ]
2069- pub fn as_complete_as_necessary ( & self , graph : & StackGraph ) -> bool {
2070- self . starts_at_endpoint ( graph) && self . ends_at_endpoint ( graph)
2071- }
2072-
2073- /// A partial path is _as complete as possible_ if we cannot extend it any further within the
2074- /// current file. This represents the maximal amount of work that we can pre-compute at index
2075- /// time.
2076- #[ cfg( feature = "partial-path-finding-v1" ) ]
2077- pub fn is_complete_as_possible ( & self , graph : & StackGraph ) -> bool {
2078- match & graph[ self . start_node ] {
2079- Node :: Root ( _) => ( ) ,
2080- node @ Node :: Scope ( _) => {
2081- if !node. is_exported_scope ( ) {
2082- return false ;
2083- }
2084- }
2085- node @ Node :: PushScopedSymbol ( _) | node @ Node :: PushSymbol ( _) => {
2086- if !node. is_reference ( ) {
2087- return false ;
2088- } else if !self . symbol_stack_precondition . can_match_empty ( ) {
2089- return false ;
2090- }
2091- }
2092- _ => return false ,
2093- }
2094-
2095- match & graph[ self . end_node ] {
2096- Node :: Root ( _) => ( ) ,
2097- Node :: JumpTo ( _) => ( ) ,
2098- node @ Node :: PopScopedSymbol ( _) | node @ Node :: PopSymbol ( _) => {
2099- if !node. is_definition ( ) {
2100- return false ;
2101- } else if !self . symbol_stack_postcondition . can_match_empty ( ) {
2102- return false ;
2103- }
2104- }
2105- _ => return false ,
2106- }
2107-
2108- true
2063+ graph[ self . end_node ] . is_endpoint ( )
21092064 }
21102065
21112066 /// Returns whether a partial path is "productive" — that is, whether it adds useful
@@ -2505,15 +2460,16 @@ impl Node {
25052460 }
25062461}
25072462
2508- #[ cfg( feature = "partial-path-finding-v1" ) ]
25092463impl PartialPaths {
2510- /// Finds all partial paths in a file, calling the `visit` closure for each one.
2464+ /// Finds a minimal set of partial paths in a file, calling the `visit` closure for each one.
25112465 ///
2512- /// This function ensures that the set of visited partial paths covers all complete
2513- /// paths, from references to definitions, when used for path stitching. Callers are
2514- /// advised _not_ to filter this set in the visitor using functions like
2515- /// [`PartialPath::is_complete_as_possible`][] or [`PartialPath::is_productive`][] as
2516- /// that may interfere with implementation changes of this function.
2466+ /// This function ensures that the set of visited partial paths
2467+ /// (a) is minimal, no path can be constructed by stitching other paths in the set, and
2468+ /// (b) covers all complete paths, from references to definitions, when used for path stitching
2469+ ///
2470+ /// Callers are advised _not_ to filter this set in the visitor using functions like
2471+ /// [`PartialPath::is_productive`][] as that may interfere with implementation changes of this
2472+ /// function.
25172473 ///
25182474 /// This function will not return until all reachable partial paths have been processed, so
25192475 /// `graph` must already contain a complete stack graph. If you have a very large stack graph
@@ -2522,7 +2478,7 @@ impl PartialPaths {
25222478 /// [`PartialPath::extend`][] manually.
25232479 ///
25242480 /// [`PartialPath::extend`]: struct.PartialPath.html#method.extend
2525- pub fn find_all_partial_paths_in_file < F > (
2481+ pub fn find_minimal_partial_paths_set_in_file < F > (
25262482 & mut self ,
25272483 graph : & StackGraph ,
25282484 file : Handle < File > ,
@@ -2532,64 +2488,11 @@ impl PartialPaths {
25322488 where
25332489 F : FnMut ( & StackGraph , & mut PartialPaths , PartialPath ) ,
25342490 {
2535- let mut cycle_detector = CycleDetector :: new ( ) ;
2536- let mut queue = VecDeque :: new ( ) ;
2537- queue. push_back ( PartialPath :: from_node ( graph, self , StackGraph :: root_node ( ) ) ) ;
2538- queue. extend (
2539- graph
2540- . nodes_for_file ( file)
2541- . filter ( |node| match & graph[ * node] {
2542- node @ Node :: PushScopedSymbol ( _) => node. is_reference ( ) ,
2543- node @ Node :: PushSymbol ( _) => node. is_reference ( ) ,
2544- node @ Node :: Scope ( _) => node. is_exported_scope ( ) ,
2545- _ => false ,
2546- } )
2547- . map ( |node| PartialPath :: from_node ( graph, self , node) ) ,
2548- ) ;
2549- while let Some ( path) = queue. pop_front ( ) {
2550- cancellation_flag. check ( "finding partial paths in file" ) ?;
2551- if !cycle_detector. should_process_path ( & path, |probe| probe. cmp ( graph, self , & path) ) {
2552- continue ;
2553- }
2554- let should_extend = path. end_node == path. start_node || !graph[ path. end_node ] . is_root ( ) ;
2555- if should_extend {
2556- path. extend_from_file ( graph, self , file, & mut queue) ;
2557- }
2558- if path. is_complete_as_possible ( graph) && path. is_productive ( self ) {
2559- visit ( graph, self , path) ;
2560- }
2491+ fn as_complete_as_necessary ( graph : & StackGraph , path : & PartialPath ) -> bool {
2492+ path. starts_at_endpoint ( graph)
2493+ && ( path. ends_at_endpoint ( graph) || graph[ path. end_node ] . is_jump_to ( ) )
25612494 }
2562- Ok ( ( ) )
2563- }
2564- }
25652495
2566- #[ cfg( not( feature = "partial-path-finding-v1" ) ) ]
2567- impl PartialPaths {
2568- /// Finds all partial paths in a file, calling the `visit` closure for each one.
2569- ///
2570- /// This function ensures that the set of visited partial paths covers all complete
2571- /// paths, from references to definitions, when used for path stitching. Callers are
2572- /// advised _not_ to filter this set in the visitor using functions like
2573- /// [`PartialPath::is_complete_as_possible`][] or [`PartialPath::is_productive`][] as
2574- /// that may interfere with implementation changes of this function.
2575- ///
2576- /// This function will not return until all reachable partial paths have been processed, so
2577- /// `graph` must already contain a complete stack graph. If you have a very large stack graph
2578- /// stored in some other storage system, and want more control over lazily loading only the
2579- /// necessary pieces, then you should code up your own loop that calls
2580- /// [`PartialPath::extend`][] manually.
2581- ///
2582- /// [`PartialPath::extend`]: struct.PartialPath.html#method.extend
2583- pub fn find_all_partial_paths_in_file < F > (
2584- & mut self ,
2585- graph : & StackGraph ,
2586- file : Handle < File > ,
2587- cancellation_flag : & dyn CancellationFlag ,
2588- mut visit : F ,
2589- ) -> Result < ( ) , CancellationError >
2590- where
2591- F : FnMut ( & StackGraph , & mut PartialPaths , PartialPath ) ,
2592- {
25932496 copious_debugging ! ( "Find all partial paths in {}" , graph[ file] ) ;
25942497 let mut cycle_detector = CycleDetector :: new ( ) ;
25952498 let mut queue = VecDeque :: new ( ) ;
@@ -2604,7 +2507,7 @@ impl PartialPaths {
26042507 cancellation_flag. check ( "finding partial paths in file" ) ?;
26052508 let is_seed = path. start_node == path. end_node && path. edges . len ( ) == 0 ;
26062509 copious_debugging ! ( " => {}" , path. display( graph, self ) ) ;
2607- if !is_seed && path . as_complete_as_necessary ( graph) {
2510+ if !is_seed && as_complete_as_necessary ( graph, & path ) {
26082511 copious_debugging ! ( " * as complete as necessary" ) ;
26092512 if !path. is_productive ( self ) {
26102513 copious_debugging ! ( " * not productive" ) ;
0 commit comments