Auto merge of #29530 - jseyfried:resolve, r=nikomatsakis
Replace `TypeNsDef` and `ValueNsDef` with a more general type `NsDef`. Define a newtype `NameBinding` for `Rc<RefCell<Option<NsDef>>>` and refactor `NameBindings` to be a `NameBinding` for each namespace. Replace uses of `NameBindings` with `NameBinding` where only one binding is being used (in `NamespaceResult`, `Target,` etc). Refactor away `resolve_definition_of_name_in_module` and `NameDefinition`, fixing issue #4952.
This commit is contained in:
commit
8e9a97529d
src
librustc_resolve
test/compile-fail
@ -18,18 +18,15 @@ use resolve_imports::ImportDirective;
|
||||
use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
|
||||
use resolve_imports::ImportResolution;
|
||||
use Module;
|
||||
use ModuleKind::*;
|
||||
use Namespace::{TypeNS, ValueNS};
|
||||
use NameBindings;
|
||||
use {names_to_string, module_to_string};
|
||||
use ParentLink::{self, ModuleParentLink, BlockParentLink};
|
||||
use Resolver;
|
||||
use resolve_imports::Shadowable;
|
||||
use TypeNsDef;
|
||||
use {resolve_error, ResolutionError};
|
||||
|
||||
use self::DuplicateCheckingMode::*;
|
||||
use self::NamespaceError::*;
|
||||
|
||||
use rustc::metadata::csearch;
|
||||
use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
|
||||
@ -62,29 +59,12 @@ use std::rc::Rc;
|
||||
// another item exists with the same name in some namespace.
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
enum DuplicateCheckingMode {
|
||||
ForbidDuplicateModules,
|
||||
ForbidDuplicateTypesAndModules,
|
||||
ForbidDuplicateTypes,
|
||||
ForbidDuplicateValues,
|
||||
ForbidDuplicateTypesAndValues,
|
||||
OverwriteDuplicates,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
enum NamespaceError {
|
||||
NoError,
|
||||
ModuleError,
|
||||
TypeError,
|
||||
ValueError,
|
||||
}
|
||||
|
||||
fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
|
||||
match ns {
|
||||
NoError => "",
|
||||
ModuleError | TypeError => "type or module",
|
||||
ValueError => "value",
|
||||
}
|
||||
}
|
||||
|
||||
struct GraphBuilder<'a, 'b: 'a, 'tcx: 'b> {
|
||||
resolver: &'a mut Resolver<'b, 'tcx>,
|
||||
}
|
||||
@ -106,121 +86,63 @@ impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
|
||||
impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
/// Constructs the reduced graph for the entire crate.
|
||||
fn build_reduced_graph(self, krate: &hir::Crate) {
|
||||
let parent = self.graph_root.get_module();
|
||||
let mut visitor = BuildReducedGraphVisitor {
|
||||
parent: self.graph_root.clone(),
|
||||
builder: self,
|
||||
parent: parent,
|
||||
};
|
||||
intravisit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
||||
/// Adds a new child item to the module definition of the parent node and
|
||||
/// returns its corresponding name bindings as well as the current parent.
|
||||
/// Or, if we're inside a block, creates (or reuses) an anonymous module
|
||||
/// corresponding to the innermost block ID and returns the name bindings
|
||||
/// as well as the newly-created parent.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if this node does not have a module definition and we are not inside
|
||||
/// a block.
|
||||
/// Adds a new child item to the module definition of the parent node,
|
||||
/// or if there is already a child, does duplicate checking on the child.
|
||||
/// Returns the child's corresponding name bindings.
|
||||
fn add_child(&self,
|
||||
name: Name,
|
||||
parent: &Rc<Module>,
|
||||
duplicate_checking_mode: DuplicateCheckingMode,
|
||||
// For printing errors
|
||||
sp: Span)
|
||||
-> Rc<NameBindings> {
|
||||
// If this is the immediate descendant of a module, then we add the
|
||||
// child name directly. Otherwise, we create or reuse an anonymous
|
||||
// module and add the child to that.
|
||||
|
||||
-> NameBindings {
|
||||
self.check_for_conflicts_between_external_crates_and_items(&**parent, name, sp);
|
||||
|
||||
// Add or reuse the child.
|
||||
let child = parent.children.borrow().get(&name).cloned();
|
||||
match child {
|
||||
None => {
|
||||
let child = Rc::new(NameBindings::new());
|
||||
let child = NameBindings::new();
|
||||
parent.children.borrow_mut().insert(name, child.clone());
|
||||
child
|
||||
}
|
||||
Some(child) => {
|
||||
// Enforce the duplicate checking mode:
|
||||
//
|
||||
// * If we're requesting duplicate module checking, check that
|
||||
// there isn't a module in the module with the same name.
|
||||
//
|
||||
// * If we're requesting duplicate type checking, check that
|
||||
// there isn't a type in the module with the same name.
|
||||
// the name isn't defined in the type namespace.
|
||||
//
|
||||
// * If we're requesting duplicate value checking, check that
|
||||
// there isn't a value in the module with the same name.
|
||||
// the name isn't defined in the value namespace.
|
||||
//
|
||||
// * If we're requesting duplicate type checking and duplicate
|
||||
// value checking, check that there isn't a duplicate type
|
||||
// and a duplicate value with the same name.
|
||||
// * If we're requesting duplicate type and value checking,
|
||||
// check that the name isn't defined in either namespace.
|
||||
//
|
||||
// * If no duplicate checking was requested at all, do
|
||||
// nothing.
|
||||
|
||||
let mut duplicate_type = NoError;
|
||||
let ns = match duplicate_checking_mode {
|
||||
ForbidDuplicateModules => {
|
||||
if child.get_module_if_available().is_some() {
|
||||
duplicate_type = ModuleError;
|
||||
}
|
||||
Some(TypeNS)
|
||||
}
|
||||
ForbidDuplicateTypesAndModules => {
|
||||
if child.defined_in_namespace(TypeNS) {
|
||||
duplicate_type = TypeError;
|
||||
}
|
||||
Some(TypeNS)
|
||||
}
|
||||
ForbidDuplicateValues => {
|
||||
if child.defined_in_namespace(ValueNS) {
|
||||
duplicate_type = ValueError;
|
||||
}
|
||||
Some(ValueNS)
|
||||
}
|
||||
ForbidDuplicateTypesAndValues => {
|
||||
let mut n = None;
|
||||
match child.def_for_namespace(TypeNS) {
|
||||
Some(DefMod(_)) | None => {}
|
||||
Some(_) => {
|
||||
n = Some(TypeNS);
|
||||
duplicate_type = TypeError;
|
||||
}
|
||||
}
|
||||
if child.defined_in_namespace(ValueNS) {
|
||||
duplicate_type = ValueError;
|
||||
n = Some(ValueNS);
|
||||
}
|
||||
n
|
||||
}
|
||||
OverwriteDuplicates => None,
|
||||
ForbidDuplicateTypes if child.type_ns.defined() => TypeNS,
|
||||
ForbidDuplicateValues if child.value_ns.defined() => ValueNS,
|
||||
ForbidDuplicateTypesAndValues if child.type_ns.defined() => TypeNS,
|
||||
ForbidDuplicateTypesAndValues if child.value_ns.defined() => ValueNS,
|
||||
_ => return child,
|
||||
};
|
||||
if duplicate_type != NoError {
|
||||
// Return an error here by looking up the namespace that
|
||||
// had the duplicate.
|
||||
let ns = ns.unwrap();
|
||||
resolve_error(
|
||||
self,
|
||||
sp,
|
||||
ResolutionError::DuplicateDefinition(
|
||||
namespace_error_to_string(duplicate_type),
|
||||
name)
|
||||
);
|
||||
{
|
||||
let r = child.span_for_namespace(ns);
|
||||
if let Some(sp) = r {
|
||||
self.session.span_note(sp,
|
||||
&format!("first definition of {} `{}` here",
|
||||
namespace_error_to_string(duplicate_type),
|
||||
name));
|
||||
}
|
||||
}
|
||||
|
||||
// Record an error here by looking up the namespace that had the duplicate
|
||||
let ns_str = match ns { TypeNS => "type or module", ValueNS => "value" };
|
||||
resolve_error(self, sp, ResolutionError::DuplicateDefinition(ns_str, name));
|
||||
|
||||
if let Some(sp) = child[ns].span() {
|
||||
let note = format!("first definition of {} `{}` here", ns_str, name);
|
||||
self.session.span_note(sp, ¬e);
|
||||
}
|
||||
child
|
||||
}
|
||||
@ -395,11 +317,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
};
|
||||
self.external_exports.insert(def_id);
|
||||
let parent_link = ModuleParentLink(Rc::downgrade(parent), name);
|
||||
let external_module = Rc::new(Module::new(parent_link,
|
||||
Some(def_id),
|
||||
NormalModuleKind,
|
||||
false,
|
||||
true));
|
||||
let def = DefMod(def_id);
|
||||
let external_module = Module::new(parent_link, Some(def), false, true);
|
||||
|
||||
debug!("(build reduced graph for item) found extern `{}`",
|
||||
module_to_string(&*external_module));
|
||||
self.check_for_conflicts_between_external_crates(&**parent, name, sp);
|
||||
@ -412,40 +332,13 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
ItemMod(..) => {
|
||||
let child = parent.children.borrow().get(&name).cloned();
|
||||
if let Some(child) = child {
|
||||
// check if there's struct of the same name already defined
|
||||
if child.defined_in_namespace(TypeNS) &&
|
||||
child.get_module_if_available().is_none() {
|
||||
self.session.span_warn(sp,
|
||||
&format!("duplicate definition of {} `{}`. \
|
||||
Defining a module and a struct with \
|
||||
the same name will be disallowed soon.",
|
||||
namespace_error_to_string(TypeError),
|
||||
name));
|
||||
{
|
||||
let r = child.span_for_namespace(TypeNS);
|
||||
if let Some(sp) = r {
|
||||
self.session.span_note(sp,
|
||||
&format!("first definition of {} `{}` here",
|
||||
namespace_error_to_string(TypeError),
|
||||
name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp);
|
||||
let name_bindings = self.add_child(name, parent, ForbidDuplicateTypes, sp);
|
||||
|
||||
let parent_link = self.get_parent_link(parent, name);
|
||||
let def_id = self.ast_map.local_def_id(item.id);
|
||||
name_bindings.define_module(parent_link,
|
||||
Some(def_id),
|
||||
NormalModuleKind,
|
||||
false,
|
||||
is_public,
|
||||
sp);
|
||||
|
||||
name_bindings.get_module()
|
||||
let def = DefMod(self.ast_map.local_def_id(item.id));
|
||||
let module = Module::new(parent_link, Some(def), false, is_public);
|
||||
name_bindings.define_module(module.clone(), sp);
|
||||
module
|
||||
}
|
||||
|
||||
ItemForeignMod(..) => parent.clone(),
|
||||
@ -477,42 +370,26 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
ItemTy(..) => {
|
||||
let name_bindings = self.add_child(name,
|
||||
parent,
|
||||
ForbidDuplicateTypesAndModules,
|
||||
ForbidDuplicateTypes,
|
||||
sp);
|
||||
|
||||
name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false),
|
||||
sp,
|
||||
modifiers);
|
||||
|
||||
let parent_link = self.get_parent_link(parent, name);
|
||||
name_bindings.set_module_kind(parent_link,
|
||||
Some(self.ast_map.local_def_id(item.id)),
|
||||
TypeModuleKind,
|
||||
false,
|
||||
is_public,
|
||||
sp);
|
||||
let def = DefTy(self.ast_map.local_def_id(item.id), false);
|
||||
let module = Module::new(parent_link, Some(def), false, is_public);
|
||||
name_bindings.define_module(module, sp);
|
||||
parent.clone()
|
||||
}
|
||||
|
||||
ItemEnum(ref enum_definition, _) => {
|
||||
let name_bindings = self.add_child(name,
|
||||
parent,
|
||||
ForbidDuplicateTypesAndModules,
|
||||
ForbidDuplicateTypes,
|
||||
sp);
|
||||
|
||||
name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), true),
|
||||
sp,
|
||||
modifiers);
|
||||
|
||||
let parent_link = self.get_parent_link(parent, name);
|
||||
name_bindings.set_module_kind(parent_link,
|
||||
Some(self.ast_map.local_def_id(item.id)),
|
||||
EnumModuleKind,
|
||||
false,
|
||||
is_public,
|
||||
sp);
|
||||
|
||||
let module = name_bindings.get_module();
|
||||
let def = DefTy(self.ast_map.local_def_id(item.id), true);
|
||||
let module = Module::new(parent_link, Some(def), false, is_public);
|
||||
name_bindings.define_module(module.clone(), sp);
|
||||
|
||||
for variant in &(*enum_definition).variants {
|
||||
let item_def_id = self.ast_map.local_def_id(item.id);
|
||||
@ -525,31 +402,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
ItemStruct(ref struct_def, _) => {
|
||||
// Adding to both Type and Value namespaces or just Type?
|
||||
let (forbid, ctor_id) = if struct_def.is_struct() {
|
||||
(ForbidDuplicateTypesAndModules, None)
|
||||
(ForbidDuplicateTypes, None)
|
||||
} else {
|
||||
let child = parent.children.borrow().get(&name).cloned();
|
||||
if let Some(child) = child {
|
||||
// check if theres a DefMod
|
||||
if let Some(DefMod(_)) = child.def_for_namespace(TypeNS) {
|
||||
self.session.span_warn(sp,
|
||||
&format!("duplicate definition of {} `{}`. \
|
||||
Defining a module and a struct \
|
||||
with the same name will be \
|
||||
disallowed soon.",
|
||||
namespace_error_to_string(TypeError),
|
||||
name));
|
||||
{
|
||||
let r = child.span_for_namespace(TypeNS);
|
||||
if let Some(sp) = r {
|
||||
self.session
|
||||
.span_note(sp,
|
||||
&format!("first definition of {} `{}` here",
|
||||
namespace_error_to_string(TypeError),
|
||||
name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(ForbidDuplicateTypesAndValues, Some(struct_def.id()))
|
||||
};
|
||||
|
||||
@ -590,20 +444,16 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
ItemTrait(_, _, _, ref items) => {
|
||||
let name_bindings = self.add_child(name,
|
||||
parent,
|
||||
ForbidDuplicateTypesAndModules,
|
||||
ForbidDuplicateTypes,
|
||||
sp);
|
||||
|
||||
let def_id = self.ast_map.local_def_id(item.id);
|
||||
|
||||
// Add all the items within to a new module.
|
||||
let parent_link = self.get_parent_link(parent, name);
|
||||
name_bindings.define_module(parent_link,
|
||||
Some(self.ast_map.local_def_id(item.id)),
|
||||
TraitModuleKind,
|
||||
false,
|
||||
is_public,
|
||||
sp);
|
||||
let module_parent = name_bindings.get_module();
|
||||
|
||||
let def_id = self.ast_map.local_def_id(item.id);
|
||||
let def = DefTrait(def_id);
|
||||
let module_parent = Module::new(parent_link, Some(def), false, is_public);
|
||||
name_bindings.define_module(module_parent.clone(), sp);
|
||||
|
||||
// Add the names of all the items to the trait info.
|
||||
for trait_item in items {
|
||||
@ -635,7 +485,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
self.trait_item_map.insert((trait_item.name, def_id), trait_item_def_id);
|
||||
}
|
||||
|
||||
name_bindings.define_type(DefTrait(def_id), sp, modifiers);
|
||||
parent.clone()
|
||||
}
|
||||
}
|
||||
@ -704,11 +553,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
{}",
|
||||
block_id);
|
||||
|
||||
let new_module = Rc::new(Module::new(BlockParentLink(Rc::downgrade(parent), block_id),
|
||||
None,
|
||||
AnonymousModuleKind,
|
||||
false,
|
||||
false));
|
||||
let parent_link = BlockParentLink(Rc::downgrade(parent), block_id);
|
||||
let new_module = Module::new(parent_link, None, false, false);
|
||||
parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone());
|
||||
new_module
|
||||
} else {
|
||||
@ -733,7 +579,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
DefModifiers::empty()
|
||||
} | DefModifiers::IMPORTABLE;
|
||||
let is_exported = is_public &&
|
||||
match new_parent.def_id.get() {
|
||||
match new_parent.def_id() {
|
||||
None => true,
|
||||
Some(did) => self.external_exports.contains(&did),
|
||||
};
|
||||
@ -741,37 +587,21 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
self.external_exports.insert(def.def_id());
|
||||
}
|
||||
|
||||
let kind = match def {
|
||||
DefTy(_, true) => EnumModuleKind,
|
||||
DefTy(_, false) | DefStruct(..) => TypeModuleKind,
|
||||
_ => NormalModuleKind,
|
||||
};
|
||||
|
||||
match def {
|
||||
DefMod(def_id) |
|
||||
DefForeignMod(def_id) |
|
||||
DefStruct(def_id) |
|
||||
DefTy(def_id, _) => {
|
||||
let type_def = child_name_bindings.type_def.borrow().clone();
|
||||
match type_def {
|
||||
Some(TypeNsDef { module_def: Some(module_def), .. }) => {
|
||||
debug!("(building reduced graph for external crate) already created \
|
||||
module");
|
||||
module_def.def_id.set(Some(def_id));
|
||||
}
|
||||
Some(_) | None => {
|
||||
debug!("(building reduced graph for external crate) building module {} {}",
|
||||
final_ident,
|
||||
is_public);
|
||||
let parent_link = self.get_parent_link(new_parent, name);
|
||||
|
||||
child_name_bindings.define_module(parent_link,
|
||||
Some(def_id),
|
||||
kind,
|
||||
true,
|
||||
is_public,
|
||||
DUMMY_SP);
|
||||
}
|
||||
DefMod(_) |
|
||||
DefForeignMod(_) |
|
||||
DefStruct(_) |
|
||||
DefTy(..) => {
|
||||
if let Some(module_def) = child_name_bindings.type_ns.module() {
|
||||
debug!("(building reduced graph for external crate) already created module");
|
||||
module_def.def.set(Some(def));
|
||||
} else {
|
||||
debug!("(building reduced graph for external crate) building module {} {}",
|
||||
final_ident,
|
||||
is_public);
|
||||
let parent_link = self.get_parent_link(new_parent, name);
|
||||
let module = Module::new(parent_link, Some(def), true, is_public);
|
||||
child_name_bindings.define_module(module, DUMMY_SP);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -807,12 +637,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
final_ident);
|
||||
// impl methods have already been defined with the correct importability
|
||||
// modifier
|
||||
let mut modifiers = match *child_name_bindings.value_def.borrow() {
|
||||
let mut modifiers = match *child_name_bindings.value_ns.borrow() {
|
||||
Some(ref def) => (modifiers & !DefModifiers::IMPORTABLE) |
|
||||
(def.modifiers & DefModifiers::IMPORTABLE),
|
||||
None => modifiers,
|
||||
};
|
||||
if new_parent.kind.get() != NormalModuleKind {
|
||||
if !new_parent.is_normal() {
|
||||
modifiers = modifiers & !DefModifiers::IMPORTABLE;
|
||||
}
|
||||
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
|
||||
@ -841,33 +671,30 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
||||
|
||||
// Define a module if necessary.
|
||||
let parent_link = self.get_parent_link(new_parent, name);
|
||||
child_name_bindings.set_module_kind(parent_link,
|
||||
Some(def_id),
|
||||
TraitModuleKind,
|
||||
true,
|
||||
is_public,
|
||||
DUMMY_SP)
|
||||
let module = Module::new(parent_link, Some(def), true, is_public);
|
||||
child_name_bindings.define_module(module, DUMMY_SP);
|
||||
}
|
||||
DefTy(..) | DefAssociatedTy(..) => {
|
||||
debug!("(building reduced graph for external crate) building type {}",
|
||||
final_ident);
|
||||
|
||||
let modifiers = match new_parent.kind.get() {
|
||||
NormalModuleKind => modifiers,
|
||||
let modifiers = match new_parent.is_normal() {
|
||||
true => modifiers,
|
||||
_ => modifiers & !DefModifiers::IMPORTABLE,
|
||||
};
|
||||
|
||||
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
||||
if let DefTy(..) = def {
|
||||
child_name_bindings.type_ns.set_modifiers(modifiers);
|
||||
} else {
|
||||
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
||||
}
|
||||
}
|
||||
DefStruct(def_id) => {
|
||||
debug!("(building reduced graph for external crate) building type and value for \
|
||||
{}",
|
||||
final_ident);
|
||||
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
||||
let fields = csearch::get_struct_field_names(&self.session.cstore, def_id);
|
||||
|
||||
if fields.is_empty() {
|
||||
@ -922,7 +749,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
|
||||
self.handle_external_def(def,
|
||||
def_visibility,
|
||||
&*child_name_bindings,
|
||||
&child_name_bindings,
|
||||
&name.as_str(),
|
||||
name,
|
||||
root);
|
||||
@ -943,7 +770,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
debug!("(populating external module) attempting to populate {}",
|
||||
module_to_string(&**module));
|
||||
|
||||
let def_id = match module.def_id.get() {
|
||||
let def_id = match module.def_id() {
|
||||
None => {
|
||||
debug!("(populating external module) ... no def ID!");
|
||||
return;
|
||||
@ -977,8 +804,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
/// crate.
|
||||
fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
|
||||
csearch::each_top_level_item_of_crate(&self.session.cstore,
|
||||
root.def_id
|
||||
.get()
|
||||
root.def_id()
|
||||
.unwrap()
|
||||
.krate,
|
||||
|def_like, name, visibility| {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,8 +18,8 @@
|
||||
// Then this operation can simply be performed as part of item (or import)
|
||||
// processing.
|
||||
|
||||
use {Module, NameBindings, Resolver};
|
||||
use Namespace::{self, TypeNS, ValueNS};
|
||||
use {Module, NameBinding, Resolver};
|
||||
use Namespace::{TypeNS, ValueNS};
|
||||
|
||||
use build_reduced_graph;
|
||||
use module_to_string;
|
||||
@ -54,7 +54,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
|
||||
// If this isn't a local krate, then bail out. We don't need to record
|
||||
// exports for nonlocal crates.
|
||||
|
||||
match module_.def_id.get() {
|
||||
match module_.def_id() {
|
||||
Some(def_id) if def_id.is_local() => {
|
||||
// OK. Continue.
|
||||
debug!("(recording exports for module subtree) recording exports for local \
|
||||
@ -79,7 +79,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
|
||||
build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
|
||||
|
||||
for (_, child_name_bindings) in module_.children.borrow().iter() {
|
||||
match child_name_bindings.get_module_if_available() {
|
||||
match child_name_bindings.type_ns.module() {
|
||||
None => {
|
||||
// Nothing to do.
|
||||
}
|
||||
@ -98,7 +98,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
|
||||
let mut exports = Vec::new();
|
||||
|
||||
self.add_exports_for_module(&mut exports, module_);
|
||||
match module_.def_id.get() {
|
||||
match module_.def_id() {
|
||||
Some(def_id) => {
|
||||
let node_id = self.ast_map.as_local_node_id(def_id).unwrap();
|
||||
self.export_map.insert(node_id, exports);
|
||||
@ -108,12 +108,11 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_exports_of_namebindings(&mut self,
|
||||
exports: &mut Vec<Export>,
|
||||
name: ast::Name,
|
||||
namebindings: &NameBindings,
|
||||
ns: Namespace) {
|
||||
match namebindings.def_for_namespace(ns) {
|
||||
fn add_export_of_namebinding(&mut self,
|
||||
exports: &mut Vec<Export>,
|
||||
name: ast::Name,
|
||||
namebinding: &NameBinding) {
|
||||
match namebinding.def() {
|
||||
Some(d) => {
|
||||
debug!("(computing exports) YES: export '{}' => {:?}",
|
||||
name,
|
||||
@ -139,7 +138,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
|
||||
match import_resolution.target_for_namespace(ns) {
|
||||
Some(target) => {
|
||||
debug!("(computing exports) maybe export '{}'", name);
|
||||
self.add_exports_of_namebindings(exports, *name, &*target.bindings, ns)
|
||||
self.add_export_of_namebinding(exports, *name, &target.binding)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
@ -150,6 +149,6 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
|
||||
|
||||
pub fn record(resolver: &mut Resolver) {
|
||||
let mut recorder = ExportRecorder { resolver: resolver };
|
||||
let root_module = recorder.graph_root.get_module();
|
||||
let root_module = recorder.graph_root.clone();
|
||||
recorder.record_exports_for_module_subtree(root_module);
|
||||
}
|
||||
|
@ -12,9 +12,8 @@ use self::ImportDirectiveSubclass::*;
|
||||
|
||||
use DefModifiers;
|
||||
use Module;
|
||||
use ModuleKind;
|
||||
use Namespace::{self, TypeNS, ValueNS};
|
||||
use NameBindings;
|
||||
use {NameBindings, NameBinding};
|
||||
use NamespaceResult::{BoundResult, UnboundResult, UnknownResult};
|
||||
use NamespaceResult;
|
||||
use NameSearchType;
|
||||
@ -86,18 +85,18 @@ impl ImportDirective {
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct Target {
|
||||
pub target_module: Rc<Module>,
|
||||
pub bindings: Rc<NameBindings>,
|
||||
pub binding: NameBinding,
|
||||
pub shadowable: Shadowable,
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub fn new(target_module: Rc<Module>,
|
||||
bindings: Rc<NameBindings>,
|
||||
binding: NameBinding,
|
||||
shadowable: Shadowable)
|
||||
-> Target {
|
||||
Target {
|
||||
target_module: target_module,
|
||||
bindings: bindings,
|
||||
binding: binding,
|
||||
shadowable: shadowable,
|
||||
}
|
||||
}
|
||||
@ -210,7 +209,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
i,
|
||||
self.resolver.unresolved_imports);
|
||||
|
||||
let module_root = self.resolver.graph_root.get_module();
|
||||
let module_root = self.resolver.graph_root.clone();
|
||||
let errors = self.resolve_imports_for_module_subtree(module_root.clone());
|
||||
|
||||
if self.resolver.unresolved_imports == 0 {
|
||||
@ -255,7 +254,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
|
||||
build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
|
||||
for (_, child_node) in module_.children.borrow().iter() {
|
||||
match child_node.get_module_if_available() {
|
||||
match child_node.type_ns.module() {
|
||||
None => {
|
||||
// Nothing to do.
|
||||
}
|
||||
@ -338,7 +337,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
// First, resolve the module path for the directive, if necessary.
|
||||
let container = if module_path.is_empty() {
|
||||
// Use the crate root.
|
||||
Some((self.resolver.graph_root.get_module(), LastMod(AllPublic)))
|
||||
Some((self.resolver.graph_root.clone(), LastMod(AllPublic)))
|
||||
} else {
|
||||
match self.resolver.resolve_module_path(module_.clone(),
|
||||
&module_path[..],
|
||||
@ -459,11 +458,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
Some(ref child_name_bindings) => {
|
||||
// pub_err makes sure we don't give the same error twice.
|
||||
let mut pub_err = false;
|
||||
if child_name_bindings.defined_in_namespace(ValueNS) {
|
||||
if child_name_bindings.value_ns.defined() {
|
||||
debug!("(resolving single import) found value binding");
|
||||
value_result = BoundResult(target_module.clone(),
|
||||
(*child_name_bindings).clone());
|
||||
if directive.is_public && !child_name_bindings.is_public(ValueNS) {
|
||||
child_name_bindings.value_ns.clone());
|
||||
if directive.is_public && !child_name_bindings.value_ns.is_public() {
|
||||
let msg = format!("`{}` is private, and cannot be reexported", source);
|
||||
let note_msg = format!("Consider marking `{}` as `pub` in the imported \
|
||||
module",
|
||||
@ -473,11 +472,12 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
pub_err = true;
|
||||
}
|
||||
}
|
||||
if child_name_bindings.defined_in_namespace(TypeNS) {
|
||||
if child_name_bindings.type_ns.defined() {
|
||||
debug!("(resolving single import) found type binding");
|
||||
type_result = BoundResult(target_module.clone(),
|
||||
(*child_name_bindings).clone());
|
||||
if !pub_err && directive.is_public && !child_name_bindings.is_public(TypeNS) {
|
||||
child_name_bindings.type_ns.clone());
|
||||
if !pub_err && directive.is_public &&
|
||||
!child_name_bindings.type_ns.is_public() {
|
||||
let msg = format!("`{}` is private, and cannot be reexported", source);
|
||||
let note_msg = format!("Consider declaring module `{}` as a `pub mod`",
|
||||
source);
|
||||
@ -540,7 +540,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
}
|
||||
Some(Target {
|
||||
target_module,
|
||||
bindings,
|
||||
binding,
|
||||
shadowable: _
|
||||
}) => {
|
||||
debug!("(resolving single import) found import in ns {:?}",
|
||||
@ -549,13 +549,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
// track used imports and extern crates as well
|
||||
this.used_imports.insert((id, namespace));
|
||||
this.record_import_use(id, source);
|
||||
match target_module.def_id.get() {
|
||||
match target_module.def_id() {
|
||||
Some(DefId{krate: kid, ..}) => {
|
||||
this.used_crates.insert(kid);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return BoundResult(target_module, bindings);
|
||||
return BoundResult(target_module, binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -591,7 +591,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
// In this case we continue as if we resolved the import and let the
|
||||
// check_for_conflicts_between_imports_and_items call below handle
|
||||
// the conflict
|
||||
match (module_.def_id.get(), target_module.def_id.get()) {
|
||||
match (module_.def_id(), target_module.def_id()) {
|
||||
(Some(id1), Some(id2)) if id1 == id2 => {
|
||||
if value_result.is_unknown() {
|
||||
value_result = UnboundResult;
|
||||
@ -624,15 +624,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
Some(module) => {
|
||||
debug!("(resolving single import) found external module");
|
||||
// track the module as used.
|
||||
match module.def_id.get() {
|
||||
match module.def_id() {
|
||||
Some(DefId{krate: kid, ..}) => {
|
||||
self.resolver.used_crates.insert(kid);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let name_bindings =
|
||||
Rc::new(Resolver::create_name_bindings_from_module(module));
|
||||
type_result = BoundResult(target_module.clone(), name_bindings);
|
||||
let name_binding = NameBinding::create_from_module(module);
|
||||
type_result = BoundResult(target_module.clone(), name_binding);
|
||||
type_used_public = true;
|
||||
}
|
||||
}
|
||||
@ -651,26 +650,25 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
};
|
||||
|
||||
match *result {
|
||||
BoundResult(ref target_module, ref name_bindings) => {
|
||||
BoundResult(ref target_module, ref name_binding) => {
|
||||
debug!("(resolving single import) found {:?} target: {:?}",
|
||||
namespace_name,
|
||||
name_bindings.def_for_namespace(namespace));
|
||||
name_binding.def());
|
||||
self.check_for_conflicting_import(&import_resolution,
|
||||
directive.span,
|
||||
target,
|
||||
namespace);
|
||||
|
||||
self.check_that_import_is_importable(&**name_bindings,
|
||||
self.check_that_import_is_importable(&name_binding,
|
||||
directive.span,
|
||||
target,
|
||||
namespace);
|
||||
target);
|
||||
|
||||
let target = Some(Target::new(target_module.clone(),
|
||||
name_bindings.clone(),
|
||||
name_binding.clone(),
|
||||
directive.shadowable));
|
||||
import_resolution.set_target_and_id(namespace, target, directive.id);
|
||||
import_resolution.is_public = directive.is_public;
|
||||
*used_public = name_bindings.defined_in_public_namespace(namespace);
|
||||
*used_public = name_binding.is_public();
|
||||
}
|
||||
UnboundResult => {
|
||||
// Continue.
|
||||
@ -705,7 +703,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
// this may resolve to either a value or a type, but for documentation
|
||||
// purposes it's good enough to just favor one over the other.
|
||||
let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| {
|
||||
let def = target.bindings.def_for_namespace(ValueNS).unwrap();
|
||||
let def = target.binding.def().unwrap();
|
||||
(def,
|
||||
if value_used_public {
|
||||
lp
|
||||
@ -714,7 +712,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
})
|
||||
});
|
||||
let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| {
|
||||
let def = target.bindings.def_for_namespace(TypeNS).unwrap();
|
||||
let def = target.binding.def().unwrap();
|
||||
(def,
|
||||
if type_used_public {
|
||||
lp
|
||||
@ -857,16 +855,15 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
|
||||
// Add external module children from the containing module.
|
||||
for (&name, module) in target_module.external_module_children.borrow().iter() {
|
||||
let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
|
||||
self.merge_import_resolution(module_,
|
||||
target_module.clone(),
|
||||
import_directive,
|
||||
name,
|
||||
name_bindings);
|
||||
NameBindings::create_from_module(module.clone()));
|
||||
}
|
||||
|
||||
// Record the destination of this import
|
||||
if let Some(did) = target_module.def_id.get() {
|
||||
if let Some(did) = target_module.def_id() {
|
||||
self.resolver.def_map.borrow_mut().insert(id,
|
||||
PathResolution {
|
||||
base_def: DefMod(did),
|
||||
@ -884,7 +881,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
containing_module: Rc<Module>,
|
||||
import_directive: &ImportDirective,
|
||||
name: Name,
|
||||
name_bindings: Rc<NameBindings>) {
|
||||
name_bindings: NameBindings) {
|
||||
let id = import_directive.id;
|
||||
let is_public = import_directive.is_public;
|
||||
|
||||
@ -904,7 +901,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
let mut merge_child_item = |namespace| {
|
||||
let modifier = DefModifiers::IMPORTABLE | DefModifiers::PUBLIC;
|
||||
|
||||
if name_bindings.defined_in_namespace_with(namespace, modifier) {
|
||||
if name_bindings[namespace].defined_with(modifier) {
|
||||
let namespace_name = match namespace {
|
||||
TypeNS => "type",
|
||||
ValueNS => "value",
|
||||
@ -922,7 +919,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
msg);
|
||||
} else {
|
||||
let target = Target::new(containing_module.clone(),
|
||||
name_bindings.clone(),
|
||||
name_bindings[namespace].clone(),
|
||||
import_directive.shadowable);
|
||||
dest_import_resolution.set_target_and_id(namespace, Some(target), id);
|
||||
}
|
||||
@ -955,16 +952,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
Some(ref target) if target.shadowable != Shadowable::Always => {
|
||||
let ns_word = match namespace {
|
||||
TypeNS => {
|
||||
if let Some(ref ty_def) = *target.bindings.type_def.borrow() {
|
||||
match ty_def.module_def {
|
||||
Some(ref module) if module.kind.get() ==
|
||||
ModuleKind::NormalModuleKind => "module",
|
||||
Some(ref module) if module.kind.get() ==
|
||||
ModuleKind::TraitModuleKind => "trait",
|
||||
_ => "type",
|
||||
}
|
||||
} else {
|
||||
"type"
|
||||
match target.binding.module() {
|
||||
Some(ref module) if module.is_normal() => "module",
|
||||
Some(ref module) if module.is_trait() => "trait",
|
||||
_ => "type",
|
||||
}
|
||||
}
|
||||
ValueNS => "value",
|
||||
@ -989,11 +980,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
|
||||
/// Checks that an import is actually importable
|
||||
fn check_that_import_is_importable(&mut self,
|
||||
name_bindings: &NameBindings,
|
||||
name_binding: &NameBinding,
|
||||
import_span: Span,
|
||||
name: Name,
|
||||
namespace: Namespace) {
|
||||
if !name_bindings.defined_in_namespace_with(namespace, DefModifiers::IMPORTABLE) {
|
||||
name: Name) {
|
||||
if !name_binding.defined_with(DefModifiers::IMPORTABLE) {
|
||||
let msg = format!("`{}` is not directly importable", name);
|
||||
span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]);
|
||||
}
|
||||
@ -1032,13 +1022,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
|
||||
match import_resolution.value_target {
|
||||
Some(ref target) if target.shadowable != Shadowable::Always => {
|
||||
if let Some(ref value) = *name_bindings.value_def.borrow() {
|
||||
if let Some(ref value) = *name_bindings.value_ns.borrow() {
|
||||
span_err!(self.resolver.session,
|
||||
import_span,
|
||||
E0255,
|
||||
"import `{}` conflicts with value in this module",
|
||||
name);
|
||||
if let Some(span) = value.value_span {
|
||||
if let Some(span) = value.span {
|
||||
self.resolver.session.span_note(span, "conflicting value here");
|
||||
}
|
||||
}
|
||||
@ -1048,11 +1038,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
|
||||
match import_resolution.type_target {
|
||||
Some(ref target) if target.shadowable != Shadowable::Always => {
|
||||
if let Some(ref ty) = *name_bindings.type_def.borrow() {
|
||||
let (what, note) = match ty.module_def {
|
||||
Some(ref module) if module.kind.get() == ModuleKind::NormalModuleKind =>
|
||||
if let Some(ref ty) = *name_bindings.type_ns.borrow() {
|
||||
let (what, note) = match ty.module() {
|
||||
Some(ref module) if module.is_normal() =>
|
||||
("existing submodule", "note conflicting module here"),
|
||||
Some(ref module) if module.kind.get() == ModuleKind::TraitModuleKind =>
|
||||
Some(ref module) if module.is_trait() =>
|
||||
("trait in this module", "note conflicting trait here"),
|
||||
_ => ("type in this module", "note conflicting type here"),
|
||||
};
|
||||
@ -1062,7 +1052,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
"import `{}` conflicts with {}",
|
||||
name,
|
||||
what);
|
||||
if let Some(span) = ty.type_span {
|
||||
if let Some(span) = ty.span {
|
||||
self.resolver.session.span_note(span, note);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ mod Foo {
|
||||
}
|
||||
|
||||
enum Foo { //~ ERROR duplicate definition of type or module `Foo`
|
||||
X //~ ERROR duplicate definition of value `X`
|
||||
X
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -16,7 +16,7 @@ mod Foo { }
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct Foo;
|
||||
//~^ WARNING duplicate definition of type or module `Foo`
|
||||
//~^ ERROR duplicate definition of type or module `Foo`
|
||||
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
@ -25,7 +25,7 @@ mod Bar { }
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct Bar(i32);
|
||||
//~^ WARNING duplicate definition of type or module `Bar`
|
||||
//~^ ERROR duplicate definition of type or module `Bar`
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -34,7 +34,7 @@ struct Baz(i32);
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
mod Baz { }
|
||||
//~^ WARNING duplicate definition of type or module `Baz`
|
||||
//~^ ERROR duplicate definition of type or module `Baz`
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -43,7 +43,7 @@ struct Qux { x: bool }
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
mod Qux { }
|
||||
//~^ WARNING duplicate definition of type or module `Qux`
|
||||
//~^ ERROR duplicate definition of type or module `Qux`
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -52,7 +52,7 @@ struct Quux;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
mod Quux { }
|
||||
//~^ WARNING duplicate definition of type or module `Quux`
|
||||
//~^ ERROR duplicate definition of type or module `Quux`
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user