use {resolve_error, ResolutionError};
use self::DuplicateCheckingMode::*;
-use self::NamespaceError::*;
use rustc::metadata::csearch;
use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
// 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>,
}
visit::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>,
// For printing errors
sp: Span)
-> 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.
-
self.check_for_conflicts_between_external_crates_and_items(&**parent, name, sp);
// Add or reuse the 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.type_ns.defined() {
- duplicate_type = TypeError;
- }
- Some(TypeNS)
- }
- ForbidDuplicateValues => {
- if child.value_ns.defined() {
- duplicate_type = ValueError;
- }
- Some(ValueNS)
- }
- ForbidDuplicateTypesAndValues => {
- let mut n = None;
- match child.type_ns.def() {
- Some(DefMod(_)) | None => {}
- Some(_) => {
- n = Some(TypeNS);
- duplicate_type = TypeError;
- }
- }
- if child.value_ns.defined() {
- 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[ns].span();
- 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
}
}
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.type_ns.defined() &&
- 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.type_ns.span();
- 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 = DefMod(self.ast_map.local_def_id(item.id));
ItemTy(..) => {
let name_bindings = self.add_child(name,
parent,
- ForbidDuplicateTypesAndModules,
+ ForbidDuplicateTypes,
sp);
let parent_link = self.get_parent_link(parent, name);
ItemEnum(ref enum_definition, _) => {
let name_bindings = self.add_child(name,
parent,
- ForbidDuplicateTypesAndModules,
+ ForbidDuplicateTypes,
sp);
let parent_link = self.get_parent_link(parent, name);
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.type_ns.def() {
- 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.type_ns.span();
- 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()))
};
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);
}
}
-// Records a possibly-private definition.
-// FIXME once #21546 is resolved, the def and module fields will never both be Some,
-// so they can be refactored into something like Result<Def, Rc<Module>>.
+// Records a possibly-private value, type, or module definition.
#[derive(Debug)]
struct NsDef {
modifiers: DefModifiers, // see note in ImportResolution about how to use this
- def: Option<Def>,
- module: Option<Rc<Module>>,
+ def_or_module: DefOrModule,
span: Option<Span>,
}
+#[derive(Debug)]
+enum DefOrModule {
+ Def(Def),
+ Module(Rc<Module>),
+}
+
impl NsDef {
fn create_from_module(module: Rc<Module>, span: Option<Span>) -> Self {
let modifiers = if module.is_public {
DefModifiers::empty()
} | DefModifiers::IMPORTABLE;
- NsDef { modifiers: modifiers, def: None, module: Some(module), span: span }
+ NsDef { modifiers: modifiers, def_or_module: DefOrModule::Module(module), span: span }
+ }
+
+ fn create_from_def(def: Def, modifiers: DefModifiers, span: Option<Span>) -> Self {
+ NsDef { modifiers: modifiers, def_or_module: DefOrModule::Def(def), span: span }
+ }
+
+ fn module(&self) -> Option<Rc<Module>> {
+ match self.def_or_module {
+ DefOrModule::Module(ref module) => Some(module.clone()),
+ DefOrModule::Def(_) => None,
+ }
}
fn def(&self) -> Option<Def> {
- match (self.def, &self.module) {
- (def @ Some(_), _) => def,
- (_, &Some(ref module)) => module.def.get(),
- _ => panic!("NsDef has neither a Def nor a Module"),
+ match self.def_or_module {
+ DefOrModule::Def(def) => Some(def),
+ DefOrModule::Module(ref module) => module.def.get(),
}
}
}
fn borrow(&self) -> ::std::cell::Ref<Option<NsDef>> { self.0.borrow() }
- // Lifted versions of the NsDef fields and method
+ // Lifted versions of the NsDef methods and fields
fn def(&self) -> Option<Def> { self.and_then(NsDef::def) }
+ fn module(&self) -> Option<Rc<Module>> { self.and_then(NsDef::module) }
fn span(&self) -> Option<Span> { self.and_then(|def| def.span) }
- fn module(&self) -> Option<Rc<Module>> { self.and_then(|def| def.module.clone()) }
fn modifiers(&self) -> Option<DefModifiers> { self.and_then(|def| Some(def.modifiers)) }
fn defined(&self) -> bool { self.borrow().is_some() }
/// Records a type definition.
fn define_type(&self, def: Def, sp: Span, modifiers: DefModifiers) {
- debug!("defining type for def {:?} with modifiers {:?}",
- def,
- modifiers);
- // Merges the type with the existing type def or creates a new one.
- self.type_ns.set(NsDef {
- modifiers: modifiers, def: Some(def), module: self.type_ns.module(), span: Some(sp)
- });
+ debug!("defining type for def {:?} with modifiers {:?}", def, modifiers);
+ self.type_ns.set(NsDef::create_from_def(def, modifiers, Some(sp)));
}
/// Records a value definition.
fn define_value(&self, def: Def, sp: Span, modifiers: DefModifiers) {
- debug!("defining value for def {:?} with modifiers {:?}",
- def,
- modifiers);
- self.value_ns.set(NsDef {
- modifiers: modifiers, def: Some(def), module: None, span: Some(sp)
- });
+ debug!("defining value for def {:?} with modifiers {:?}", def, modifiers);
+ self.value_ns.set(NsDef::create_from_def(def, modifiers, Some(sp)));
}
/// Returns the module node if applicable.
self.used_imports.insert((id, namespace));
self.record_import_use(id, name);
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
- self.used_crates.insert(kid);
+ self.used_crates.insert(kid);
}
return Success((target, false));
}