]> git.lizzy.rs Git - rust.git/commitdiff
Avoid using the hir map when visibility checking in `resolve`
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Wed, 27 Apr 2016 02:29:59 +0000 (02:29 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Wed, 27 Apr 2016 06:40:54 +0000 (06:40 +0000)
Refactor `ty::Visibility` methods to use a new trait `NodeIdTree` instead of the ast map.

src/librustc/ty/mod.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs

index 238856197feedf9b07e7f7c20091cc780cad9f8e..0c23f5332982dc5620419d139b394aca38b8e9e7 100644 (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 @@ pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: &TyCtxt) -> Self
     }
 
     /// 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 @@ pub fn is_accessible_from(self, block: NodeId, map: &ast_map::Map) -> bool {
             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)
     }
 }
 
index c63776ad9ba8875b43823aedd26dfa71bba74b08..fdb834a32fbc65564debf27b02799e802bebf036 100644 (file)
@@ -1121,6 +1121,21 @@ fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
     }
 }
 
+impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> {
+    fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
+        let ancestor = self.ast_map.local_def_id(ancestor);
+        let mut module = *self.module_map.get(&node).unwrap();
+        loop {
+            if module.def_id() == Some(ancestor) { return true; }
+            let module_parent = match self.get_nearest_normal_module_parent(module) {
+                Some(parent) => parent,
+                None => return false,
+            };
+            module = module_parent;
+        }
+    }
+}
+
 impl<'a, 'tcx> Resolver<'a, 'tcx> {
     fn new(session: &'a Session,
            ast_map: &'a hir_map::Map<'tcx>,
@@ -1131,6 +1146,8 @@ fn new(session: &'a Session,
         let graph_root =
             ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas);
         let graph_root = arenas.alloc_module(graph_root);
+        let mut module_map = NodeMap();
+        module_map.insert(CRATE_NODE_ID, graph_root);
 
         Resolver {
             session: session,
@@ -1161,7 +1178,7 @@ fn new(session: &'a Session,
             freevars_seen: NodeMap(),
             export_map: NodeMap(),
             trait_map: NodeMap(),
-            module_map: NodeMap(),
+            module_map: module_map,
             used_imports: HashSet::new(),
             used_crates: HashSet::new(),
 
@@ -3343,7 +3360,7 @@ fn resolve_visibility(&mut self, vis: &hir::Visibility) -> ty::Visibility {
     fn is_accessible(&self, vis: ty::Visibility) -> bool {
         let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module);
         let node_id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap();
-        vis.is_accessible_from(node_id, &self.ast_map)
+        vis.is_accessible_from(node_id, self)
     }
 
     fn check_privacy(&mut self, name: Name, binding: &'a NameBinding<'a>, span: Span) {
index 4a87ffe820d4a9bb7d4ea64d8ba5b3738ccc7718..f0639a8517686e343f8d0a450e6255d34a60e07b 100644 (file)
@@ -552,9 +552,9 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
             _ => (),
         }
 
-        let ast_map = self.resolver.ast_map;
         match (&value_result, &type_result) {
-            (&Success(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis, ast_map) &&
+            (&Success(binding), _) if !binding.pseudo_vis()
+                                              .is_at_least(directive.vis, self.resolver) &&
                                       self.resolver.is_accessible(binding.vis) => {
                 let msg = format!("`{}` is private, and cannot be reexported", source);
                 let note_msg = format!("consider marking `{}` as `pub` in the imported module",
@@ -564,7 +564,8 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
                     .emit();
             }
 
-            (_, &Success(binding)) if !binding.pseudo_vis().is_at_least(directive.vis, ast_map) &&
+            (_, &Success(binding)) if !binding.pseudo_vis()
+                                              .is_at_least(directive.vis, self.resolver) &&
                                       self.resolver.is_accessible(binding.vis) => {
                 if binding.is_extern_crate() {
                     let msg = format!("extern crate `{}` is private, and cannot be reexported \
@@ -691,7 +692,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>, report_unresolved_impo
 
             if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
                 if ns == TypeNS && orig_binding.is_variant() &&
-                   !orig_binding.vis.is_at_least(binding.vis, &self.resolver.ast_map) {
+                   !orig_binding.vis.is_at_least(binding.vis, self.resolver) {
                     let msg = format!("variant `{}` is private, and cannot be reexported \
                                        (error E0364), consider declaring its enum as `pub`",
                                       name);