Skip to content

Commit 6aa9145

Browse files
committed
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.
1 parent 33bb269 commit 6aa9145

File tree

3 files changed

+44
-16
lines changed

3 files changed

+44
-16
lines changed

src/librustc/ty/mod.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,22 @@ pub enum Visibility {
283283
PrivateExternal,
284284
}
285285

286+
pub trait NodeIdTree {
287+
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool;
288+
}
289+
290+
impl<'a> NodeIdTree for ast_map::Map<'a> {
291+
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
292+
let mut node_ancestor = node;
293+
loop {
294+
if node_ancestor == ancestor { return true }
295+
let node_ancestor_parent = self.get_module_parent(node_ancestor);
296+
if node_ancestor_parent == node_ancestor { return false }
297+
node_ancestor = node_ancestor_parent;
298+
}
299+
}
300+
}
301+
286302
impl Visibility {
287303
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: &TyCtxt) -> Self {
288304
match *visibility {
@@ -301,7 +317,7 @@ impl Visibility {
301317
}
302318

303319
/// Returns true if an item with this visibility is accessible from the given block.
304-
pub fn is_accessible_from(self, block: NodeId, map: &ast_map::Map) -> bool {
320+
pub fn is_accessible_from<T: NodeIdTree>(self, block: NodeId, tree: &T) -> bool {
305321
let restriction = match self {
306322
// Public items are visible everywhere.
307323
Visibility::Public => return true,
@@ -311,24 +327,18 @@ impl Visibility {
311327
Visibility::Restricted(module) => module,
312328
};
313329

314-
let mut block_ancestor = block;
315-
loop {
316-
if block_ancestor == restriction { return true }
317-
let block_ancestor_parent = map.get_module_parent(block_ancestor);
318-
if block_ancestor_parent == block_ancestor { return false }
319-
block_ancestor = block_ancestor_parent;
320-
}
330+
tree.is_descendant_of(block, restriction)
321331
}
322332

323333
/// Returns true if this visibility is at least as accessible as the given visibility
324-
pub fn is_at_least(self, vis: Visibility, map: &ast_map::Map) -> bool {
334+
pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
325335
let vis_restriction = match vis {
326336
Visibility::Public => return self == Visibility::Public,
327337
Visibility::PrivateExternal => return true,
328338
Visibility::Restricted(module) => module,
329339
};
330340

331-
self.is_accessible_from(vis_restriction, map)
341+
self.is_accessible_from(vis_restriction, tree)
332342
}
333343
}
334344

src/librustc_resolve/lib.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,21 @@ impl<'a> ResolverArenas<'a> {
11211121
}
11221122
}
11231123

1124+
impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> {
1125+
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
1126+
let ancestor = self.ast_map.local_def_id(ancestor);
1127+
let mut module = *self.module_map.get(&node).unwrap();
1128+
loop {
1129+
if module.def_id() == Some(ancestor) { return true; }
1130+
let module_parent = match self.get_nearest_normal_module_parent(module) {
1131+
Some(parent) => parent,
1132+
None => return false,
1133+
};
1134+
module = module_parent;
1135+
}
1136+
}
1137+
}
1138+
11241139
impl<'a, 'tcx> Resolver<'a, 'tcx> {
11251140
fn new(session: &'a Session,
11261141
ast_map: &'a hir_map::Map<'tcx>,
@@ -1131,6 +1146,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11311146
let graph_root =
11321147
ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas);
11331148
let graph_root = arenas.alloc_module(graph_root);
1149+
let mut module_map = NodeMap();
1150+
module_map.insert(CRATE_NODE_ID, graph_root);
11341151

11351152
Resolver {
11361153
session: session,
@@ -1161,7 +1178,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11611178
freevars_seen: NodeMap(),
11621179
export_map: NodeMap(),
11631180
trait_map: NodeMap(),
1164-
module_map: NodeMap(),
1181+
module_map: module_map,
11651182
used_imports: HashSet::new(),
11661183
used_crates: HashSet::new(),
11671184

@@ -3343,7 +3360,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
33433360
fn is_accessible(&self, vis: ty::Visibility) -> bool {
33443361
let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module);
33453362
let node_id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap();
3346-
vis.is_accessible_from(node_id, &self.ast_map)
3363+
vis.is_accessible_from(node_id, self)
33473364
}
33483365

33493366
fn check_privacy(&mut self, name: Name, binding: &'a NameBinding<'a>, span: Span) {

src/librustc_resolve/resolve_imports.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -552,9 +552,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
552552
_ => (),
553553
}
554554

555-
let ast_map = self.resolver.ast_map;
556555
match (&value_result, &type_result) {
557-
(&Success(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis, ast_map) &&
556+
(&Success(binding), _) if !binding.pseudo_vis()
557+
.is_at_least(directive.vis, self.resolver) &&
558558
self.resolver.is_accessible(binding.vis) => {
559559
let msg = format!("`{}` is private, and cannot be reexported", source);
560560
let note_msg = format!("consider marking `{}` as `pub` in the imported module",
@@ -564,7 +564,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
564564
.emit();
565565
}
566566

567-
(_, &Success(binding)) if !binding.pseudo_vis().is_at_least(directive.vis, ast_map) &&
567+
(_, &Success(binding)) if !binding.pseudo_vis()
568+
.is_at_least(directive.vis, self.resolver) &&
568569
self.resolver.is_accessible(binding.vis) => {
569570
if binding.is_extern_crate() {
570571
let msg = format!("extern crate `{}` is private, and cannot be reexported \
@@ -691,7 +692,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
691692

692693
if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
693694
if ns == TypeNS && orig_binding.is_variant() &&
694-
!orig_binding.vis.is_at_least(binding.vis, &self.resolver.ast_map) {
695+
!orig_binding.vis.is_at_least(binding.vis, self.resolver) {
695696
let msg = format!("variant `{}` is private, and cannot be reexported \
696697
(error E0364), consider declaring its enum as `pub`",
697698
name);

0 commit comments

Comments
 (0)