Avoid using the hir map when visibility checking in resolve

Refactor `ty::Visibility` methods to use a new trait `NodeIdTree` instead of the ast map.
This commit is contained in:
Jeffrey Seyfried 2016-04-27 02:29:59 +00:00
parent 33bb26998c
commit 6aa9145753
3 changed files with 44 additions and 16 deletions

View file

@ -283,6 +283,22 @@ pub enum Visibility {
PrivateExternal,
}
pub trait NodeIdTree {
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool;
}
impl<'a> NodeIdTree for ast_map::Map<'a> {
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
let mut node_ancestor = node;
loop {
if node_ancestor == ancestor { return true }
let node_ancestor_parent = self.get_module_parent(node_ancestor);
if node_ancestor_parent == node_ancestor { return false }
node_ancestor = node_ancestor_parent;
}
}
}
impl Visibility {
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: &TyCtxt) -> Self {
match *visibility {
@ -301,7 +317,7 @@ impl Visibility {
}
/// Returns true if an item with this visibility is accessible from the given block.
pub fn is_accessible_from(self, block: NodeId, map: &ast_map::Map) -> bool {
pub fn is_accessible_from<T: NodeIdTree>(self, block: NodeId, tree: &T) -> bool {
let restriction = match self {
// Public items are visible everywhere.
Visibility::Public => return true,
@ -311,24 +327,18 @@ impl Visibility {
Visibility::Restricted(module) => module,
};
let mut block_ancestor = block;
loop {
if block_ancestor == restriction { return true }
let block_ancestor_parent = map.get_module_parent(block_ancestor);
if block_ancestor_parent == block_ancestor { return false }
block_ancestor = block_ancestor_parent;
}
tree.is_descendant_of(block, restriction)
}
/// Returns true if this visibility is at least as accessible as the given visibility
pub fn is_at_least(self, vis: Visibility, map: &ast_map::Map) -> bool {
pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
let vis_restriction = match vis {
Visibility::Public => return self == Visibility::Public,
Visibility::PrivateExternal => return true,
Visibility::Restricted(module) => module,
};
self.is_accessible_from(vis_restriction, map)
self.is_accessible_from(vis_restriction, tree)
}
}