@@ -23,8 +23,6 @@ use syntax::source_map::Spanned;
23
23
use syntax:: ext:: base:: MacroKind ;
24
24
use syntax_pos:: { Span , DUMMY_SP } ;
25
25
26
- use std:: result:: Result :: Err ;
27
-
28
26
pub mod blocks;
29
27
mod collector;
30
28
mod def_collector;
@@ -183,6 +181,44 @@ pub struct Map<'hir> {
183
181
hir_to_node_id : FxHashMap < HirId , NodeId > ,
184
182
}
185
183
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
+
186
222
impl < ' hir > Map < ' hir > {
187
223
#[ inline]
188
224
fn lookup ( & self , id : HirId ) -> Option < & Entry < ' hir > > {
@@ -684,45 +720,6 @@ impl<'hir> Map<'hir> {
684
720
}
685
721
}
686
722
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
-
726
723
/// Retrieves the `HirId` for `id`'s enclosing method, unless there's a
727
724
/// `while` or `loop` before reaching it, as block tail returns are not
728
725
/// available in them.
@@ -746,46 +743,41 @@ impl<'hir> Map<'hir> {
746
743
/// }
747
744
/// ```
748
745
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 {
751
748
Node :: Item ( _) |
752
749
Node :: ForeignItem ( _) |
753
750
Node :: TraitItem ( _) |
754
751
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) ,
761
753
Node :: Expr ( ref expr) => {
762
754
match expr. node {
763
- ExprKind :: Loop ( ..) | ExprKind :: Ret ( ..) => true ,
764
- _ => false ,
755
+ ExprKind :: Loop ( ..) | ExprKind :: Ret ( ..) => return None ,
756
+ _ => { }
765
757
}
766
758
}
767
- _ => false ,
759
+ _ => { }
768
760
}
769
- } ;
770
-
771
- self . walk_parent_nodes ( id, match_fn, match_non_returning_block) . ok ( )
761
+ }
762
+ None
772
763
}
773
764
774
765
/// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no
775
766
/// parent item is in this map. The "parent item" is the closest parent node
776
767
/// in the HIR which is recorded by the map and is an item, either an item
777
768
/// in a module, trait, or impl.
778
769
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
+ }
788
779
}
780
+ hir_id
789
781
}
790
782
791
783
/// Returns the `DefId` of `id`'s nearest module parent, or `id` itself if no
@@ -797,58 +789,62 @@ impl<'hir> Map<'hir> {
797
789
/// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
798
790
/// module parent is in this map.
799
791
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
+ }
806
796
}
797
+ CRATE_HIR_ID
807
798
}
808
799
809
800
/// Returns the nearest enclosing scope. A scope is roughly an item or block.
810
801
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
845
841
}
846
842
847
843
/// Returns the defining scope for an opaque type definition.
848
844
pub fn get_defining_scope ( & self , id : HirId ) -> Option < HirId > {
849
845
let mut scope = id;
850
846
loop {
851
- scope = self . get_enclosing_scope ( scope) ? ;
847
+ scope = self . get_enclosing_scope ( scope) . unwrap_or ( CRATE_HIR_ID ) ;
852
848
if scope == CRATE_HIR_ID {
853
849
return Some ( CRATE_HIR_ID ) ;
854
850
}
0 commit comments