@@ -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 > > {
@@ -682,45 +718,6 @@ impl<'hir> Map<'hir> {
682
718
}
683
719
}
684
720
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
-
724
721
/// Retrieves the `HirId` for `id`'s enclosing method, unless there's a
725
722
/// `while` or `loop` before reaching it, as block tail returns are not
726
723
/// available in them.
@@ -744,46 +741,41 @@ impl<'hir> Map<'hir> {
744
741
/// }
745
742
/// ```
746
743
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 {
749
746
Node :: Item ( _) |
750
747
Node :: ForeignItem ( _) |
751
748
Node :: TraitItem ( _) |
752
749
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) ,
759
751
Node :: Expr ( ref expr) => {
760
752
match expr. kind {
761
- ExprKind :: Loop ( ..) | ExprKind :: Ret ( ..) => true ,
762
- _ => false ,
753
+ ExprKind :: Loop ( ..) | ExprKind :: Ret ( ..) => return None ,
754
+ _ => { }
763
755
}
764
756
}
765
- _ => false ,
757
+ _ => { }
766
758
}
767
- } ;
768
-
769
- self . walk_parent_nodes ( id, match_fn, match_non_returning_block) . ok ( )
759
+ }
760
+ None
770
761
}
771
762
772
763
/// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no
773
764
/// parent item is in this map. The "parent item" is the closest parent node
774
765
/// in the HIR which is recorded by the map and is an item, either an item
775
766
/// in a module, trait, or impl.
776
767
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
+ }
786
777
}
778
+ hir_id
787
779
}
788
780
789
781
/// Returns the `DefId` of `id`'s nearest module parent, or `id` itself if no
@@ -795,58 +787,62 @@ impl<'hir> Map<'hir> {
795
787
/// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
796
788
/// module parent is in this map.
797
789
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
+ }
804
794
}
795
+ CRATE_HIR_ID
805
796
}
806
797
807
798
/// Returns the nearest enclosing scope. A scope is roughly an item or block.
808
799
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
843
839
}
844
840
845
841
/// Returns the defining scope for an opaque type definition.
846
842
pub fn get_defining_scope ( & self , id : HirId ) -> Option < HirId > {
847
843
let mut scope = id;
848
844
loop {
849
- scope = self . get_enclosing_scope ( scope) ? ;
845
+ scope = self . get_enclosing_scope ( scope) . unwrap_or ( CRATE_HIR_ID ) ;
850
846
if scope == CRATE_HIR_ID {
851
847
return Some ( CRATE_HIR_ID ) ;
852
848
}
0 commit comments