Skip to content

Commit 5122091

Browse files
committed
Turn walk_parent_nodes method into an iterator
1 parent 6ef275e commit 5122091

File tree

1 file changed

+101
-105
lines changed

1 file changed

+101
-105
lines changed

src/librustc/hir/map/mod.rs

+101-105
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ use syntax::source_map::Spanned;
2323
use syntax::ext::base::MacroKind;
2424
use syntax_pos::{Span, DUMMY_SP};
2525

26-
use std::result::Result::Err;
27-
2826
pub mod blocks;
2927
mod collector;
3028
mod 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+
186222
impl<'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

Comments
 (0)