@@ -23,8 +23,6 @@ use syntax::source_map::Spanned;
2323use syntax:: ext:: base:: MacroKind ;
2424use syntax_pos:: { Span , DUMMY_SP } ;
2525
26- use std:: result:: Result :: Err ;
27-
2826pub mod blocks;
2927mod collector;
3028mod def_collector;
@@ -183,6 +181,44 @@ pub struct Map<'hir> {
183181 hir_to_node_id : FxHashMap < HirId , NodeId > ,
184182}
185183
184+ struct ParentHirIterator < ' map > {
185+ current_id : HirId ,
186+ map : & ' map Map < ' map > ,
187+ }
188+
189+ impl < ' map > ParentHirIterator < ' map > {
190+ fn new ( current_id : HirId , map : & ' map Map < ' map > ) -> ParentHirIterator < ' map > {
191+ ParentHirIterator {
192+ current_id,
193+ map,
194+ }
195+ }
196+ }
197+
198+ impl < ' map > Iterator for ParentHirIterator < ' map > {
199+ type Item = ( HirId , Node < ' map > ) ;
200+
201+ fn next ( & mut self ) -> Option < Self :: Item > {
202+ if self . current_id == CRATE_HIR_ID {
203+ return None ;
204+ }
205+ loop { // There are nodes that do not have entries, so we need to skip them.
206+ let parent_id = self . map . get_parent_node ( self . current_id ) ;
207+
208+ if parent_id == self . current_id {
209+ self . current_id = CRATE_HIR_ID ;
210+ return None ;
211+ }
212+
213+ self . current_id = parent_id;
214+ if let Some ( entry) = self . map . find_entry ( parent_id) {
215+ return Some ( ( parent_id, entry. node ) ) ;
216+ }
217+ // If this `HirId` doesn't have an `Entry`, skip it and look for its `parent_id`.
218+ }
219+ }
220+ }
221+
186222impl < ' hir > Map < ' hir > {
187223 #[ inline]
188224 fn lookup ( & self , id : HirId ) -> Option < & Entry < ' hir > > {
@@ -684,45 +720,6 @@ impl<'hir> Map<'hir> {
684720 }
685721 }
686722
687-
688- /// If there is some error when walking the parents (e.g., a node does not
689- /// have a parent in the map or a node can't be found), then we return the
690- /// last good `HirId` we found. Note that reaching the crate root (`id == 0`),
691- /// is not an error, since items in the crate module have the crate root as
692- /// parent.
693- fn walk_parent_nodes < F , F2 > ( & self ,
694- start_id : HirId ,
695- found : F ,
696- bail_early : F2 )
697- -> Result < HirId , HirId >
698- where F : Fn ( & Node < ' hir > ) -> bool , F2 : Fn ( & Node < ' hir > ) -> bool
699- {
700- let mut id = start_id;
701- loop {
702- let parent_id = self . get_parent_node ( id) ;
703- if parent_id == CRATE_HIR_ID {
704- return Ok ( CRATE_HIR_ID ) ;
705- }
706- if parent_id == id {
707- return Err ( id) ;
708- }
709-
710- if let Some ( entry) = self . find_entry ( parent_id) {
711- if let Node :: Crate = entry. node {
712- return Err ( id) ;
713- }
714- if found ( & entry. node ) {
715- return Ok ( parent_id) ;
716- } else if bail_early ( & entry. node ) {
717- return Err ( parent_id) ;
718- }
719- id = parent_id;
720- } else {
721- return Err ( id) ;
722- }
723- }
724- }
725-
726723 /// Retrieves the `HirId` for `id`'s enclosing method, unless there's a
727724 /// `while` or `loop` before reaching it, as block tail returns are not
728725 /// available in them.
@@ -746,46 +743,41 @@ impl<'hir> Map<'hir> {
746743 /// }
747744 /// ```
748745 pub fn get_return_block ( & self , id : HirId ) -> Option < HirId > {
749- let match_fn = | node : & Node < ' _ > | {
750- match * node {
746+ for ( hir_id , node) in ParentHirIterator :: new ( id , & self ) {
747+ match node {
751748 Node :: Item ( _) |
752749 Node :: ForeignItem ( _) |
753750 Node :: TraitItem ( _) |
754751 Node :: Expr ( Expr { node : ExprKind :: Closure ( ..) , ..} ) |
755- Node :: ImplItem ( _) => true ,
756- _ => false ,
757- }
758- } ;
759- let match_non_returning_block = |node : & Node < ' _ > | {
760- match * node {
752+ Node :: ImplItem ( _) => return Some ( hir_id) ,
761753 Node :: Expr ( ref expr) => {
762754 match expr. node {
763- ExprKind :: Loop ( ..) | ExprKind :: Ret ( ..) => true ,
764- _ => false ,
755+ ExprKind :: Loop ( ..) | ExprKind :: Ret ( ..) => return None ,
756+ _ => { }
765757 }
766758 }
767- _ => false ,
759+ _ => { }
768760 }
769- } ;
770-
771- self . walk_parent_nodes ( id, match_fn, match_non_returning_block) . ok ( )
761+ }
762+ None
772763 }
773764
774765 /// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no
775766 /// parent item is in this map. The "parent item" is the closest parent node
776767 /// in the HIR which is recorded by the map and is an item, either an item
777768 /// in a module, trait, or impl.
778769 pub fn get_parent_item ( & self , hir_id : HirId ) -> HirId {
779- match self . walk_parent_nodes ( hir_id, | node| match * node {
780- Node :: Item ( _ ) |
781- Node :: ForeignItem ( _ ) |
782- Node :: TraitItem ( _) |
783- Node :: ImplItem ( _) => true ,
784- _ => false ,
785- } , |_| false ) {
786- Ok ( id ) => id ,
787- Err ( id ) => id ,
770+ for ( hir_id, node) in ParentHirIterator :: new ( hir_id , & self ) {
771+ match node {
772+ Node :: Crate |
773+ Node :: Item ( _) |
774+ Node :: ForeignItem ( _) |
775+ Node :: TraitItem ( _ ) |
776+ Node :: ImplItem ( _ ) => return hir_id ,
777+ _ => { }
778+ }
788779 }
780+ hir_id
789781 }
790782
791783 /// Returns the `DefId` of `id`'s nearest module parent, or `id` itself if no
@@ -797,58 +789,62 @@ impl<'hir> Map<'hir> {
797789 /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
798790 /// module parent is in this map.
799791 pub fn get_module_parent_node ( & self , hir_id : HirId ) -> HirId {
800- match self . walk_parent_nodes ( hir_id, |node| match * node {
801- Node :: Item ( & Item { node : ItemKind :: Mod ( _) , .. } ) => true ,
802- _ => false ,
803- } , |_| false ) {
804- Ok ( id) => id,
805- Err ( id) => id,
792+ for ( hir_id, node) in ParentHirIterator :: new ( hir_id, & self ) {
793+ if let Node :: Item ( & Item { node : ItemKind :: Mod ( _) , .. } ) = node {
794+ return hir_id;
795+ }
806796 }
797+ CRATE_HIR_ID
807798 }
808799
809800 /// Returns the nearest enclosing scope. A scope is roughly an item or block.
810801 pub fn get_enclosing_scope ( & self , hir_id : HirId ) -> Option < HirId > {
811- self . walk_parent_nodes ( hir_id, |node| match * node {
812- Node :: Item ( i) => {
813- match i. node {
814- ItemKind :: Fn ( ..)
815- | ItemKind :: Mod ( ..)
816- | ItemKind :: Enum ( ..)
817- | ItemKind :: Struct ( ..)
818- | ItemKind :: Union ( ..)
819- | ItemKind :: Trait ( ..)
820- | ItemKind :: Impl ( ..) => true ,
821- _ => false ,
822- }
823- } ,
824- Node :: ForeignItem ( fi) => {
825- match fi. node {
826- ForeignItemKind :: Fn ( ..) => true ,
827- _ => false ,
828- }
829- } ,
830- Node :: TraitItem ( ti) => {
831- match ti. node {
832- TraitItemKind :: Method ( ..) => true ,
833- _ => false ,
834- }
835- } ,
836- Node :: ImplItem ( ii) => {
837- match ii. node {
838- ImplItemKind :: Method ( ..) => true ,
839- _ => false ,
840- }
841- } ,
842- Node :: Block ( _) => true ,
843- _ => false ,
844- } , |_| false ) . ok ( )
802+ for ( hir_id, node) in ParentHirIterator :: new ( hir_id, & self ) {
803+ if match node {
804+ Node :: Item ( i) => {
805+ match i. node {
806+ ItemKind :: Fn ( ..)
807+ | ItemKind :: Mod ( ..)
808+ | ItemKind :: Enum ( ..)
809+ | ItemKind :: Struct ( ..)
810+ | ItemKind :: Union ( ..)
811+ | ItemKind :: Trait ( ..)
812+ | ItemKind :: Impl ( ..) => true ,
813+ _ => false ,
814+ }
815+ } ,
816+ Node :: ForeignItem ( fi) => {
817+ match fi. node {
818+ ForeignItemKind :: Fn ( ..) => true ,
819+ _ => false ,
820+ }
821+ } ,
822+ Node :: TraitItem ( ti) => {
823+ match ti. node {
824+ TraitItemKind :: Method ( ..) => true ,
825+ _ => false ,
826+ }
827+ } ,
828+ Node :: ImplItem ( ii) => {
829+ match ii. node {
830+ ImplItemKind :: Method ( ..) => true ,
831+ _ => false ,
832+ }
833+ } ,
834+ Node :: Block ( _) => true ,
835+ _ => false ,
836+ } {
837+ return Some ( hir_id) ;
838+ }
839+ }
840+ None
845841 }
846842
847843 /// Returns the defining scope for an opaque type definition.
848844 pub fn get_defining_scope ( & self , id : HirId ) -> Option < HirId > {
849845 let mut scope = id;
850846 loop {
851- scope = self . get_enclosing_scope ( scope) ? ;
847+ scope = self . get_enclosing_scope ( scope) . unwrap_or ( CRATE_HIR_ID ) ;
852848 if scope == CRATE_HIR_ID {
853849 return Some ( CRATE_HIR_ID ) ;
854850 }
0 commit comments