Skip to content
32 changes: 22 additions & 10 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,24 @@ 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;
while node_ancestor != ancestor {
let node_ancestor_parent = self.get_module_parent(node_ancestor);
if node_ancestor_parent == node_ancestor {
return false;
}
node_ancestor = node_ancestor_parent;
}
true
}
}

impl Visibility {
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: &TyCtxt) -> Self {
match *visibility {
Expand All @@ -301,7 +319,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,
Expand All @@ -311,24 +329,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)
}
}

Expand Down
51 changes: 28 additions & 23 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ trait ToNameBinding<'a> {
fn to_name_binding(self) -> NameBinding<'a>;
}

impl<'a> ToNameBinding<'a> for (Module<'a>, Span) {
impl<'a> ToNameBinding<'a> for (Module<'a>, Span, ty::Visibility) {
fn to_name_binding(self) -> NameBinding<'a> {
NameBinding::create_from_module(self.0, Some(self.1))
NameBinding { kind: NameBindingKind::Module(self.0), span: self.1, vis: self.2 }
}
}

impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
fn to_name_binding(self) -> NameBinding<'a> {
NameBinding { kind: NameBindingKind::Def(self.0), span: Some(self.1), vis: self.2 }
NameBinding { kind: NameBindingKind::Def(self.0), span: self.1, vis: self.2 }
}
}

Expand Down Expand Up @@ -247,8 +247,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
};
let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(def_id);
let module = self.new_extern_crate_module(parent_link, def, vis, item.id);
self.define(parent, name, TypeNS, (module, sp));
let module = self.new_extern_crate_module(parent_link, def, item.id);
self.define(parent, name, TypeNS, (module, sp, vis));

self.build_reduced_graph_for_external_crate(module);
}
Expand All @@ -257,8 +257,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
ItemMod(..) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(self.ast_map.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false, vis);
self.define(parent, name, TypeNS, (module, sp));
let module = self.new_module(parent_link, Some(def), false);
self.define(parent, name, TypeNS, (module, sp, vis));
self.module_map.insert(item.id, module);
*parent_ref = module;
}
Expand Down Expand Up @@ -289,12 +289,12 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
ItemEnum(ref enum_definition, _) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Enum(self.ast_map.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false, vis);
self.define(parent, name, TypeNS, (module, sp));
let module = self.new_module(parent_link, Some(def), false);
self.define(parent, name, TypeNS, (module, sp, vis));

for variant in &(*enum_definition).variants {
let item_def_id = self.ast_map.local_def_id(item.id);
self.build_reduced_graph_for_variant(variant, item_def_id, module);
self.build_reduced_graph_for_variant(variant, item_def_id, module, vis);
}
}

Expand Down Expand Up @@ -328,21 +328,25 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
// Add all the items within to a new module.
let parent_link = ModuleParentLink(parent, name);
let def = Def::Trait(def_id);
let module_parent = self.new_module(parent_link, Some(def), false, vis);
self.define(parent, name, TypeNS, (module_parent, sp));
let module_parent = self.new_module(parent_link, Some(def), false);
self.define(parent, name, TypeNS, (module_parent, sp, vis));

// Add the names of all the items to the trait info.
for item in items {
let item_def_id = self.ast_map.local_def_id(item.id);
let mut is_static_method = false;
let (def, ns) = match item.node {
hir::ConstTraitItem(..) => (Def::AssociatedConst(item_def_id), ValueNS),
hir::MethodTraitItem(..) => (Def::Method(item_def_id), ValueNS),
hir::MethodTraitItem(ref sig, _) => {
is_static_method = sig.explicit_self.node == hir::SelfStatic;
(Def::Method(item_def_id), ValueNS)
}
hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
};

self.define(module_parent, item.name, ns, (def, item.span, vis));

self.trait_item_map.insert((item.name, def_id), item_def_id);
self.trait_item_map.insert((item.name, def_id), is_static_method);
}
}
}
Expand All @@ -353,7 +357,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
fn build_reduced_graph_for_variant(&mut self,
variant: &Variant,
item_id: DefId,
parent: Module<'b>) {
parent: Module<'b>,
vis: ty::Visibility) {
let name = variant.node.name;
if variant.node.data.is_struct() {
// Not adding fields for variants as they are not accessed with a self receiver
Expand All @@ -364,8 +369,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
// Variants are always treated as importable to allow them to be glob used.
// All variants are defined in both type and value namespaces as future-proofing.
let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id()));
self.define(parent, name, ValueNS, (def, variant.span, parent.vis));
self.define(parent, name, TypeNS, (def, variant.span, parent.vis));
self.define(parent, name, ValueNS, (def, variant.span, vis));
self.define(parent, name, TypeNS, (def, variant.span, vis));
}

/// Constructs the reduced graph for one foreign item.
Expand Down Expand Up @@ -396,7 +401,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
block_id);

let parent_link = BlockParentLink(parent, block_id);
let new_module = self.new_module(parent_link, None, false, parent.vis);
let new_module = self.new_module(parent_link, None, false);
self.module_map.insert(block_id, new_module);
*parent = new_module;
}
Expand Down Expand Up @@ -425,8 +430,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
debug!("(building reduced graph for external crate) building module {} {:?}",
name, vis);
let parent_link = ModuleParentLink(parent, name);
let module = self.new_module(parent_link, Some(def), true, vis);
self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
let module = self.new_module(parent_link, Some(def), true);
self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
}
Def::Variant(_, variant_id) => {
debug!("(building reduced graph for external crate) building variant {}", name);
Expand Down Expand Up @@ -463,12 +468,12 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
'{}'",
trait_item_name);

self.trait_item_map.insert((trait_item_name, def_id), trait_item_def.def_id());
self.trait_item_map.insert((trait_item_name, def_id), false);
}

let parent_link = ModuleParentLink(parent, name);
let module = self.new_module(parent_link, Some(def), true, vis);
self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
let module = self.new_module(parent_link, Some(def), true);
self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
}
Def::TyAlias(..) | Def::AssociatedTy(..) => {
debug!("(building reduced graph for external crate) building type {}", name);
Expand Down
Loading