Skip to content

Commit faee8e1

Browse files
committed
Turn walk_parent_nodes method into an iterator
1 parent 590ae0e commit faee8e1

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>> {
@@ -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

Comments
 (0)