@@ -14,6 +14,15 @@ pub(crate) enum ImportPathElement {
1414 Item ( DefId ) ,
1515}
1616
17+ impl ImportPathElement {
18+ pub fn def_id ( & self ) -> DefId {
19+ match self {
20+ Self :: Rename ( did, _) => * did,
21+ Self :: Item ( did) => * did,
22+ }
23+ }
24+ }
25+
1726impl std:: fmt:: Debug for ImportPathElement {
1827 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
1928 match self {
@@ -55,11 +64,12 @@ impl<'tcx> ImportPathFinder<'tcx> {
5564 fn crawl_module ( & mut self , did : DefId , frontier : & [ ImportPathElement ] ) {
5665 trace ! ( "Crawling module {did:?}" ) ;
5766
67+ // Push current module onto the path frontier
5868 let mut new_frontier = frontier. to_vec ( ) ;
5969 new_frontier. push ( ImportPathElement :: Item ( did) ) ;
60- // do not allow modification or weird things happen
6170 let new_frontier = & new_frontier;
6271
72+ // Get children of the module
6373 let children = if did. is_local ( ) {
6474 self . tcx . module_children_local ( did. expect_local ( ) )
6575 } else {
@@ -69,15 +79,16 @@ impl<'tcx> ImportPathFinder<'tcx> {
6979 for child in children {
7080 let rename = child. ident . to_string ( ) ;
7181
82+ // Skip private items if we don't include them
7283 if !self . include_private_paths && !child. vis . is_public ( ) {
7384 trace ! ( "Skipping private child {rename:?}" ) ;
7485 continue ;
7586 }
7687
77- let did = if let Some ( did ) = child . res . opt_def_id ( ) {
78- did
79- } else {
80- continue ;
88+ // Skip if the child has no DefId
89+ let did = match child . res . opt_def_id ( ) {
90+ Some ( did ) => did ,
91+ None => continue ,
8192 } ;
8293
8394 trace ! (
@@ -87,16 +98,24 @@ impl<'tcx> ImportPathFinder<'tcx> {
8798 ) ;
8899
89100 match self . tcx . def_kind ( did) {
90- DefKind :: Mod => self . crawl_module ( did, new_frontier) ,
91- DefKind :: Struct | DefKind :: Union | DefKind :: Enum | DefKind :: Trait => {
92- // save the rename and the def id
101+ DefKind :: Mod => {
102+ // Only recurse if this DefId is not already in the current path
103+ if new_frontier. iter ( ) . any ( |el| el. def_id ( ) == did) {
104+ trace ! ( "Cycle detected for {did:?}, skipping recursion" ) ;
105+ continue ;
106+ }
107+ self . crawl_module ( did, new_frontier)
108+ }
93109
94- let mut new_frontier = new_frontier. clone ( ) ;
95- new_frontier. push ( ImportPathElement :: Rename ( did, rename) ) ;
110+ DefKind :: Struct | DefKind :: Union | DefKind :: Enum | DefKind :: Trait => {
111+ // Save the rename and the DefId
112+ let mut path_for_item = new_frontier. clone ( ) ;
113+ path_for_item. push ( ImportPathElement :: Rename ( did, rename) ) ;
96114
97- trace ! ( "saving import path for {did:?}: {new_frontier :?}" ) ;
98- self . cache . entry ( did) . or_default ( ) . push ( new_frontier ) ;
115+ trace ! ( "Saving import path for {did:?}: {path_for_item :?}" ) ;
116+ self . cache . entry ( did) . or_default ( ) . push ( path_for_item ) ;
99117 }
118+
100119 _ => continue ,
101120 }
102121 }
0 commit comments