@@ -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 > > {
@@ -682,45 +718,6 @@ impl<'hir> Map<'hir> {
682718 }
683719 }
684720
685-
686- /// If there is some error when walking the parents (e.g., a node does not
687- /// have a parent in the map or a node can't be found), then we return the
688- /// last good `HirId` we found. Note that reaching the crate root (`id == 0`),
689- /// is not an error, since items in the crate module have the crate root as
690- /// parent.
691- fn walk_parent_nodes < F , F2 > ( & self ,
692- start_id : HirId ,
693- found : F ,
694- bail_early : F2 )
695- -> Result < HirId , HirId >
696- where F : Fn ( & Node < ' hir > ) -> bool , F2 : Fn ( & Node < ' hir > ) -> bool
697- {
698- let mut id = start_id;
699- loop {
700- let parent_id = self . get_parent_node ( id) ;
701- if parent_id == CRATE_HIR_ID {
702- return Ok ( CRATE_HIR_ID ) ;
703- }
704- if parent_id == id {
705- return Err ( id) ;
706- }
707-
708- if let Some ( entry) = self . find_entry ( parent_id) {
709- if let Node :: Crate = entry. node {
710- return Err ( id) ;
711- }
712- if found ( & entry. node ) {
713- return Ok ( parent_id) ;
714- } else if bail_early ( & entry. node ) {
715- return Err ( parent_id) ;
716- }
717- id = parent_id;
718- } else {
719- return Err ( id) ;
720- }
721- }
722- }
723-
724721 /// Retrieves the `HirId` for `id`'s enclosing method, unless there's a
725722 /// `while` or `loop` before reaching it, as block tail returns are not
726723 /// available in them.
@@ -744,46 +741,41 @@ impl<'hir> Map<'hir> {
744741 /// }
745742 /// ```
746743 pub fn get_return_block ( & self , id : HirId ) -> Option < HirId > {
747- let match_fn = | node : & Node < ' _ > | {
748- match * node {
744+ for ( hir_id , node) in ParentHirIterator :: new ( id , & self ) {
745+ match node {
749746 Node :: Item ( _) |
750747 Node :: ForeignItem ( _) |
751748 Node :: TraitItem ( _) |
752749 Node :: Expr ( Expr { kind : ExprKind :: Closure ( ..) , ..} ) |
753- Node :: ImplItem ( _) => true ,
754- _ => false ,
755- }
756- } ;
757- let match_non_returning_block = |node : & Node < ' _ > | {
758- match * node {
750+ Node :: ImplItem ( _) => return Some ( hir_id) ,
759751 Node :: Expr ( ref expr) => {
760752 match expr. kind {
761- ExprKind :: Loop ( ..) | ExprKind :: Ret ( ..) => true ,
762- _ => false ,
753+ ExprKind :: Loop ( ..) | ExprKind :: Ret ( ..) => return None ,
754+ _ => { }
763755 }
764756 }
765- _ => false ,
757+ _ => { }
766758 }
767- } ;
768-
769- self . walk_parent_nodes ( id, match_fn, match_non_returning_block) . ok ( )
759+ }
760+ None
770761 }
771762
772763 /// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no
773764 /// parent item is in this map. The "parent item" is the closest parent node
774765 /// in the HIR which is recorded by the map and is an item, either an item
775766 /// in a module, trait, or impl.
776767 pub fn get_parent_item ( & self , hir_id : HirId ) -> HirId {
777- match self . walk_parent_nodes ( hir_id, | node| match * node {
778- Node :: Item ( _ ) |
779- Node :: ForeignItem ( _ ) |
780- Node :: TraitItem ( _) |
781- Node :: ImplItem ( _) => true ,
782- _ => false ,
783- } , |_| false ) {
784- Ok ( id ) => id ,
785- Err ( id ) => id ,
768+ for ( hir_id, node) in ParentHirIterator :: new ( hir_id , & self ) {
769+ match node {
770+ Node :: Crate |
771+ Node :: Item ( _) |
772+ Node :: ForeignItem ( _) |
773+ Node :: TraitItem ( _ ) |
774+ Node :: ImplItem ( _ ) => return hir_id ,
775+ _ => { }
776+ }
786777 }
778+ hir_id
787779 }
788780
789781 /// Returns the `DefId` of `id`'s nearest module parent, or `id` itself if no
@@ -795,58 +787,62 @@ impl<'hir> Map<'hir> {
795787 /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
796788 /// module parent is in this map.
797789 pub fn get_module_parent_node ( & self , hir_id : HirId ) -> HirId {
798- match self . walk_parent_nodes ( hir_id, |node| match * node {
799- Node :: Item ( & Item { kind : ItemKind :: Mod ( _) , .. } ) => true ,
800- _ => false ,
801- } , |_| false ) {
802- Ok ( id) => id,
803- Err ( id) => id,
790+ for ( hir_id, node) in ParentHirIterator :: new ( hir_id, & self ) {
791+ if let Node :: Item ( & Item { kind : ItemKind :: Mod ( _) , .. } ) = node {
792+ return hir_id;
793+ }
804794 }
795+ CRATE_HIR_ID
805796 }
806797
807798 /// Returns the nearest enclosing scope. A scope is roughly an item or block.
808799 pub fn get_enclosing_scope ( & self , hir_id : HirId ) -> Option < HirId > {
809- self . walk_parent_nodes ( hir_id, |node| match * node {
810- Node :: Item ( i) => {
811- match i. kind {
812- ItemKind :: Fn ( ..)
813- | ItemKind :: Mod ( ..)
814- | ItemKind :: Enum ( ..)
815- | ItemKind :: Struct ( ..)
816- | ItemKind :: Union ( ..)
817- | ItemKind :: Trait ( ..)
818- | ItemKind :: Impl ( ..) => true ,
819- _ => false ,
820- }
821- } ,
822- Node :: ForeignItem ( fi) => {
823- match fi. kind {
824- ForeignItemKind :: Fn ( ..) => true ,
825- _ => false ,
826- }
827- } ,
828- Node :: TraitItem ( ti) => {
829- match ti. kind {
830- TraitItemKind :: Method ( ..) => true ,
831- _ => false ,
832- }
833- } ,
834- Node :: ImplItem ( ii) => {
835- match ii. kind {
836- ImplItemKind :: Method ( ..) => true ,
837- _ => false ,
838- }
839- } ,
840- Node :: Block ( _) => true ,
841- _ => false ,
842- } , |_| false ) . ok ( )
800+ for ( hir_id, node) in ParentHirIterator :: new ( hir_id, & self ) {
801+ if match node {
802+ Node :: Item ( i) => {
803+ match i. kind {
804+ ItemKind :: Fn ( ..)
805+ | ItemKind :: Mod ( ..)
806+ | ItemKind :: Enum ( ..)
807+ | ItemKind :: Struct ( ..)
808+ | ItemKind :: Union ( ..)
809+ | ItemKind :: Trait ( ..)
810+ | ItemKind :: Impl ( ..) => true ,
811+ _ => false ,
812+ }
813+ } ,
814+ Node :: ForeignItem ( fi) => {
815+ match fi. kind {
816+ ForeignItemKind :: Fn ( ..) => true ,
817+ _ => false ,
818+ }
819+ } ,
820+ Node :: TraitItem ( ti) => {
821+ match ti. kind {
822+ TraitItemKind :: Method ( ..) => true ,
823+ _ => false ,
824+ }
825+ } ,
826+ Node :: ImplItem ( ii) => {
827+ match ii. kind {
828+ ImplItemKind :: Method ( ..) => true ,
829+ _ => false ,
830+ }
831+ } ,
832+ Node :: Block ( _) => true ,
833+ _ => false ,
834+ } {
835+ return Some ( hir_id) ;
836+ }
837+ }
838+ None
843839 }
844840
845841 /// Returns the defining scope for an opaque type definition.
846842 pub fn get_defining_scope ( & self , id : HirId ) -> Option < HirId > {
847843 let mut scope = id;
848844 loop {
849- scope = self . get_enclosing_scope ( scope) ? ;
845+ scope = self . get_enclosing_scope ( scope) . unwrap_or ( CRATE_HIR_ID ) ;
850846 if scope == CRATE_HIR_ID {
851847 return Some ( CRATE_HIR_ID ) ;
852848 }
0 commit comments