diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3481f1bfd5203..c669e847bf2dd 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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, }; 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, duplicate_checking_mode: DuplicateCheckingMode, // For printing errors sp: Span) - -> Rc { - // 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) { csearch::each_top_level_item_of_crate(&self.session.cstore, - root.def_id - .get() + root.def_id() .unwrap() .krate, |def_like, name, visibility| { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a402d8310f96a..e9d714c5524e0 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -39,7 +39,6 @@ extern crate rustc; use self::PatternBindingMode::*; use self::Namespace::*; use self::NamespaceResult::*; -use self::NameDefinition::*; use self::ResolveResult::*; use self::FallbackSuggestion::*; use self::TypeParameters::*; @@ -50,7 +49,6 @@ use self::AssocItemResolveResult::*; use self::NameSearchType::*; use self::BareIdentifierPatternResolution::*; use self::ParentLink::*; -use self::ModuleKind::*; use self::FallbackChecks::*; use rustc::front::map as hir_map; @@ -513,8 +511,8 @@ enum NamespaceResult { /// not bound in the namespace. UnboundResult, /// Means that resolve has determined that the name is bound in the Module - /// argument, and specified by the NameBindings argument. - BoundResult(Rc, Rc), + /// argument, and specified by the NameBinding argument. + BoundResult(Rc, NameBinding), } impl NamespaceResult { @@ -532,15 +530,6 @@ impl NamespaceResult { } } -enum NameDefinition { - // The name was unbound. - NoNameDefinition, - // The name identifies an immediate child. - ChildNameDefinition(Def, LastPrivate), - // The name identifies an import. - ImportNameDefinition(Def, LastPrivate), -} - impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { fn visit_item(&mut self, item: &Item) { execute_callback!(hir_map::Node::NodeItem(item), self); @@ -769,24 +758,13 @@ enum ParentLink { BlockParentLink(Weak, NodeId), } -/// The type of module this is. -#[derive(Copy, Clone, PartialEq, Debug)] -enum ModuleKind { - NormalModuleKind, - TraitModuleKind, - EnumModuleKind, - TypeModuleKind, - AnonymousModuleKind, -} - /// One node in the tree of modules. pub struct Module { parent_link: ParentLink, - def_id: Cell>, - kind: Cell, + def: Cell>, is_public: bool, - children: RefCell>>, + children: RefCell>, imports: RefCell>, // The external module children of this node that were declared with @@ -832,15 +810,13 @@ pub struct Module { impl Module { fn new(parent_link: ParentLink, - def_id: Option, - kind: ModuleKind, + def: Option, external: bool, is_public: bool) - -> Module { - Module { + -> Rc { + Rc::new(Module { parent_link: parent_link, - def_id: Cell::new(def_id), - kind: Cell::new(kind), + def: Cell::new(def), is_public: is_public, children: RefCell::new(HashMap::new()), imports: RefCell::new(Vec::new()), @@ -852,6 +828,24 @@ impl Module { pub_glob_count: Cell::new(0), resolved_import_count: Cell::new(0), populated: Cell::new(!external), + }) + } + + fn def_id(&self) -> Option { + self.def.get().as_ref().map(Def::def_id) + } + + fn is_normal(&self) -> bool { + match self.def.get() { + Some(DefMod(_)) | Some(DefForeignMod(_)) => true, + _ => false, + } + } + + fn is_trait(&self) -> bool { + match self.def.get() { + Some(DefTrait(_)) => true, + _ => false, } } @@ -892,9 +886,8 @@ impl Module { impl fmt::Debug for Module { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, - "{:?}, kind: {:?}, {}", - self.def_id, - self.kind, + "{:?}, {}", + self.def, if self.is_public { "public" } else { @@ -911,263 +904,155 @@ bitflags! { } } -// Records a possibly-private type definition. -#[derive(Clone,Debug)] -struct TypeNsDef { - modifiers: DefModifiers, // see note in ImportResolution about how to use this - module_def: Option>, - type_def: Option, - type_span: Option, -} - -// Records a possibly-private value definition. -#[derive(Clone, Copy, Debug)] -struct ValueNsDef { +// 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: Def, - value_span: Option, + def_or_module: DefOrModule, + span: Option, } -// Records the definitions (at most one for each namespace) that a name is -// bound to. #[derive(Debug)] -pub struct NameBindings { - type_def: RefCell>, // < Meaning in type namespace. - value_def: RefCell>, // < Meaning in value namespace. +enum DefOrModule { + Def(Def), + Module(Rc), } -impl NameBindings { - fn new() -> NameBindings { - NameBindings { - type_def: RefCell::new(None), - value_def: RefCell::new(None), - } - } - - /// Creates a new module in this set of name bindings. - fn define_module(&self, - parent_link: ParentLink, - def_id: Option, - kind: ModuleKind, - external: bool, - is_public: bool, - sp: Span) { - // Merges the module with the existing type def or creates a new one. - let modifiers = if is_public { +impl NsDef { + fn create_from_module(module: Rc, span: Option) -> Self { + let modifiers = if module.is_public { DefModifiers::PUBLIC } else { DefModifiers::empty() } | DefModifiers::IMPORTABLE; - let module_ = Rc::new(Module::new(parent_link, def_id, kind, external, is_public)); - let type_def = self.type_def.borrow().clone(); - match type_def { - None => { - *self.type_def.borrow_mut() = Some(TypeNsDef { - modifiers: modifiers, - module_def: Some(module_), - type_def: None, - type_span: Some(sp), - }); - } - Some(type_def) => { - *self.type_def.borrow_mut() = Some(TypeNsDef { - modifiers: modifiers, - module_def: Some(module_), - type_span: Some(sp), - type_def: type_def.type_def, - }); - } - } + + NsDef { modifiers: modifiers, def_or_module: DefOrModule::Module(module), span: span } } - /// Sets the kind of the module, creating a new one if necessary. - fn set_module_kind(&self, - parent_link: ParentLink, - def_id: Option, - kind: ModuleKind, - external: bool, - is_public: bool, - _sp: Span) { - let modifiers = if is_public { - DefModifiers::PUBLIC - } else { - DefModifiers::empty() - } | DefModifiers::IMPORTABLE; - let type_def = self.type_def.borrow().clone(); - match type_def { - None => { - let module = Module::new(parent_link, def_id, kind, external, is_public); - *self.type_def.borrow_mut() = Some(TypeNsDef { - modifiers: modifiers, - module_def: Some(Rc::new(module)), - type_def: None, - type_span: None, - }); - } - Some(type_def) => { - match type_def.module_def { - None => { - let module = Module::new(parent_link, def_id, kind, external, is_public); - *self.type_def.borrow_mut() = Some(TypeNsDef { - modifiers: modifiers, - module_def: Some(Rc::new(module)), - type_def: type_def.type_def, - type_span: None, - }); - } - Some(module_def) => module_def.kind.set(kind), - } - } + fn create_from_def(def: Def, modifiers: DefModifiers, span: Option) -> Self { + NsDef { modifiers: modifiers, def_or_module: DefOrModule::Def(def), span: span } + } + + fn module(&self) -> Option> { + match self.def_or_module { + DefOrModule::Module(ref module) => Some(module.clone()), + DefOrModule::Def(_) => None, } } - /// 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. - let type_def = self.type_def.borrow().clone(); - match type_def { - None => { - *self.type_def.borrow_mut() = Some(TypeNsDef { - module_def: None, - type_def: Some(def), - type_span: Some(sp), - modifiers: modifiers, - }); - } - Some(type_def) => { - *self.type_def.borrow_mut() = Some(TypeNsDef { - module_def: type_def.module_def, - type_def: Some(def), - type_span: Some(sp), - modifiers: modifiers, - }); - } + fn def(&self) -> Option { + match self.def_or_module { + DefOrModule::Def(def) => Some(def), + DefOrModule::Module(ref module) => module.def.get(), } } +} - /// 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_def.borrow_mut() = Some(ValueNsDef { - def: def, - value_span: Some(sp), - modifiers: modifiers, - }); +// Records at most one definition that a name in a namespace is bound to +#[derive(Clone,Debug)] +pub struct NameBinding(Rc>>); + +impl NameBinding { + fn new() -> Self { + NameBinding(Rc::new(RefCell::new(None))) } - /// Returns the module node if applicable. - fn get_module_if_available(&self) -> Option> { - match *self.type_def.borrow() { - Some(ref type_def) => type_def.module_def.clone(), - None => None, - } + fn create_from_module(module: Rc) -> Self { + NameBinding(Rc::new(RefCell::new(Some(NsDef::create_from_module(module, None))))) } - /// Returns the module node. Panics if this node does not have a module - /// definition. - fn get_module(&self) -> Rc { - match self.get_module_if_available() { - None => { - panic!("get_module called on a node with no module definition!") - } - Some(module_def) => module_def, - } + fn set(&self, ns_def: NsDef) { + *self.0.borrow_mut() = Some(ns_def); } - fn defined_in_namespace(&self, namespace: Namespace) -> bool { - match namespace { - TypeNS => return self.type_def.borrow().is_some(), - ValueNS => return self.value_def.borrow().is_some(), + fn set_modifiers(&self, modifiers: DefModifiers) { + if let Some(ref mut ns_def) = *self.0.borrow_mut() { + ns_def.modifiers = modifiers } } - fn defined_in_public_namespace(&self, namespace: Namespace) -> bool { - self.defined_in_namespace_with(namespace, DefModifiers::PUBLIC) + fn borrow(&self) -> ::std::cell::Ref> { + self.0.borrow() } - fn defined_in_namespace_with(&self, namespace: Namespace, modifiers: DefModifiers) -> bool { - match namespace { - TypeNS => match *self.type_def.borrow() { - Some(ref def) => def.modifiers.contains(modifiers), - None => false, - }, - ValueNS => match *self.value_def.borrow() { - Some(ref def) => def.modifiers.contains(modifiers), - None => false, - }, - } + // Lifted versions of the NsDef methods and fields + fn def(&self) -> Option { + self.borrow().as_ref().and_then(NsDef::def) + } + fn module(&self) -> Option> { + self.borrow().as_ref().and_then(NsDef::module) + } + fn span(&self) -> Option { + self.borrow().as_ref().and_then(|def| def.span) + } + fn modifiers(&self) -> Option { + self.borrow().as_ref().and_then(|def| Some(def.modifiers)) } - fn def_for_namespace(&self, namespace: Namespace) -> Option { - match namespace { - TypeNS => { - match *self.type_def.borrow() { - None => None, - Some(ref type_def) => { - match type_def.type_def { - Some(type_def) => Some(type_def), - None => { - match type_def.module_def { - Some(ref module) => { - match module.def_id.get() { - Some(did) => Some(DefMod(did)), - None => None, - } - } - None => None, - } - } - } - } - } - } - ValueNS => { - match *self.value_def.borrow() { - None => None, - Some(value_def) => Some(value_def.def), - } - } - } + fn defined(&self) -> bool { + self.borrow().is_some() } - fn span_for_namespace(&self, namespace: Namespace) -> Option { - if self.defined_in_namespace(namespace) { - match namespace { - TypeNS => { - match *self.type_def.borrow() { - None => None, - Some(ref type_def) => type_def.type_span, - } - } - ValueNS => { - match *self.value_def.borrow() { - None => None, - Some(ref value_def) => value_def.value_span, - } - } - } - } else { - None + fn defined_with(&self, modifiers: DefModifiers) -> bool { + self.modifiers().map(|m| m.contains(modifiers)).unwrap_or(false) + } + + fn is_public(&self) -> bool { + self.defined_with(DefModifiers::PUBLIC) + } + + fn def_and_lp(&self) -> (Def, LastPrivate) { + let def = self.def().unwrap(); + (def, LastMod(if self.is_public() { AllPublic } else { DependsOn(def.def_id()) })) + } +} + +// Records the definitions (at most one for each namespace) that a name is +// bound to. +#[derive(Clone,Debug)] +pub struct NameBindings { + type_ns: NameBinding, // < Meaning in type namespace. + value_ns: NameBinding, // < Meaning in value namespace. +} + +impl ::std::ops::Index for NameBindings { + type Output = NameBinding; + fn index(&self, namespace: Namespace) -> &NameBinding { + match namespace { TypeNS => &self.type_ns, ValueNS => &self.value_ns } + } +} + +impl NameBindings { + fn new() -> NameBindings { + NameBindings { + type_ns: NameBinding::new(), + value_ns: NameBinding::new(), } } - fn is_public(&self, namespace: Namespace) -> bool { - match namespace { - TypeNS => { - let type_def = self.type_def.borrow(); - type_def.as_ref().unwrap().modifiers.contains(DefModifiers::PUBLIC) - } - ValueNS => { - let value_def = self.value_def.borrow(); - value_def.as_ref().unwrap().modifiers.contains(DefModifiers::PUBLIC) - } + fn create_from_module(module: Rc) -> NameBindings { + NameBindings { + type_ns: NameBinding::create_from_module(module), + value_ns: NameBinding::new(), } } + + /// Creates a new module in this set of name bindings. + fn define_module(&self, module: Rc, sp: Span) { + self.type_ns.set(NsDef::create_from_module(module, Some(sp))); + } + + /// Records a type definition. + fn define_type(&self, def: Def, sp: Span, modifiers: DefModifiers) { + 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::create_from_def(def, modifiers, Some(sp))); + } } /// Interns the names of the primitive types. @@ -1209,7 +1094,7 @@ pub struct Resolver<'a, 'tcx: 'a> { ast_map: &'a hir_map::Map<'tcx>, - graph_root: NameBindings, + graph_root: Rc, trait_item_map: FnvHashMap<(Name, DefId), DefId>, @@ -1276,20 +1161,10 @@ enum FallbackChecks { impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>, - crate_span: Span, make_glob_map: MakeGlobMap) -> Resolver<'a, 'tcx> { - let graph_root = NameBindings::new(); - let root_def_id = ast_map.local_def_id(CRATE_NODE_ID); - graph_root.define_module(NoParentLink, - Some(root_def_id), - NormalModuleKind, - false, - true, - crate_span); - - let current_module = graph_root.get_module(); + let graph_root = Module::new(NoParentLink, Some(DefMod(root_def_id)), false, true); Resolver { session: session, @@ -1298,14 +1173,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // The outermost module has def ID 0; this is not reflected in the // AST. - graph_root: graph_root, + graph_root: graph_root.clone(), trait_item_map: FnvHashMap(), structs: FnvHashMap(), unresolved_imports: 0, - current_module: current_module, + current_module: graph_root, value_ribs: Vec::new(), type_ribs: Vec::new(), label_ribs: Vec::new(), @@ -1356,18 +1231,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn create_name_bindings_from_module(module: Rc) -> NameBindings { - NameBindings { - type_def: RefCell::new(Some(TypeNsDef { - modifiers: DefModifiers::IMPORTABLE, - module_def: Some(module), - type_def: None, - type_span: None, - })), - value_def: RefCell::new(None), - } - } - /// Checks that the names of external crates don't collide with other /// external crates. fn check_for_conflicts_between_external_crates(&self, @@ -1473,38 +1336,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Success((target, used_proxy)) => { // Check to see whether there are type bindings, and, if // so, whether there is a module within. - match *target.bindings.type_def.borrow() { - Some(ref type_def) => { - match type_def.module_def { - None => { - let msg = format!("Not a module `{}`", name); - - return Failed(Some((span, msg))); - } - Some(ref module_def) => { - search_module = module_def.clone(); + if let Some(module_def) = target.binding.module() { + // track extern crates for unused_extern_crate lint + if let Some(did) = module_def.def_id() { + self.used_crates.insert(did.krate); + } - // track extern crates for unused_extern_crate lint - if let Some(did) = module_def.def_id.get() { - self.used_crates.insert(did.krate); - } + search_module = module_def; - // Keep track of the closest - // private module used when - // resolving this import chain. - if !used_proxy && !search_module.is_public { - if let Some(did) = search_module.def_id.get() { - closest_private = LastMod(DependsOn(did)); - } - } - } + // Keep track of the closest private module used + // when resolving this import chain. + if !used_proxy && !search_module.is_public { + if let Some(did) = search_module.def_id() { + closest_private = LastMod(DependsOn(did)); } } - None => { - // There are no type bindings at all. - let msg = format!("Not a module `{}`", name); - return Failed(Some((span, msg))); - } + } else { + let msg = format!("Not a module `{}`", name); + return Failed(Some((span, msg))); } } } @@ -1571,7 +1420,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { DontUseLexicalScope => { // This is a crate-relative path. We will start the // resolution process at index zero. - search_module = self.graph_root.get_module(); + search_module = self.graph_root.clone(); start_index = 0; last_private = LastMod(AllPublic); } @@ -1597,8 +1446,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Success(PrefixFound(ref containing_module, index)) => { search_module = containing_module.clone(); start_index = index; - last_private = LastMod(DependsOn(containing_module.def_id - .get() + last_private = LastMod(DependsOn(containing_module.def_id() .unwrap())); } } @@ -1628,10 +1476,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { build_reduced_graph::populate_module_if_necessary(self, &module_); match module_.children.borrow().get(&name) { - Some(name_bindings) if name_bindings.defined_in_namespace(namespace) => { + Some(name_bindings) if name_bindings[namespace].defined() => { debug!("top name bindings succeeded"); return Success((Target::new(module_.clone(), - name_bindings.clone(), + name_bindings[namespace].clone(), Shadowable::Never), false)); } @@ -1658,7 +1506,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let id = import_resolution.id(namespace); self.used_imports.insert((id, namespace)); self.record_import_use(id, name); - if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() { + if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() { self.used_crates.insert(kid); } return Success((target, false)); @@ -1671,9 +1519,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // FIXME (21114): In principle unclear `child` *has* to be lifted. let child = module_.external_module_children.borrow().get(&name).cloned(); if let Some(module) = child { - let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module)); + let name_binding = NameBinding::create_from_module(module); debug!("lower name bindings succeeded"); - return Success((Target::new(module_, name_bindings, Shadowable::Never), + return Success((Target::new(module_, name_binding, Shadowable::Never), false)); } } @@ -1689,19 +1537,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Failed(None); } ModuleParentLink(parent_module_node, _) => { - match search_module.kind.get() { - NormalModuleKind => { - // We stop the search here. - debug!("(resolving item in lexical scope) unresolved module: not \ - searching through module parents"); + if search_module.is_normal() { + // We stop the search here. + debug!("(resolving item in lexical scope) unresolved module: not \ + searching through module parents"); return Failed(None); - } - TraitModuleKind | - EnumModuleKind | - TypeModuleKind | - AnonymousModuleKind => { - search_module = parent_module_node.upgrade().unwrap(); - } + } else { + search_module = parent_module_node.upgrade().unwrap(); } } BlockParentLink(ref parent_module_node, _) => { @@ -1745,26 +1587,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS); match resolve_result { Success((target, _)) => { - let bindings = &*target.bindings; - match *bindings.type_def.borrow() { - Some(ref type_def) => { - match type_def.module_def { - None => { - debug!("!!! (resolving module in lexical scope) module wasn't \ - actually a module!"); - return Failed(None); - } - Some(ref module_def) => { - return Success(module_def.clone()); - } - } - } - None => { - debug!("!!! (resolving module in lexical scope) module - \ - wasn't actually a module!"); - return Failed(None); - } + if let Some(module_def) = target.binding.module() { + return Success(module_def) + } else { + debug!("!!! (resolving module in lexical scope) module \ + wasn't actually a module!"); + return Failed(None); } } Indeterminate => { @@ -1787,13 +1615,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ModuleParentLink(new_module, _) | BlockParentLink(new_module, _) => { let new_module = new_module.upgrade().unwrap(); - match new_module.kind.get() { - NormalModuleKind => return Some(new_module), - TraitModuleKind | - EnumModuleKind | - TypeModuleKind | - AnonymousModuleKind => module_ = new_module, + if new_module.is_normal() { + return Some(new_module); } + module_ = new_module; } } } @@ -1802,17 +1627,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Returns the nearest normal module parent of the given module, or the /// module itself if it is a normal module. fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc) -> Rc { - match module_.kind.get() { - NormalModuleKind => return module_, - TraitModuleKind | - EnumModuleKind | - TypeModuleKind | - AnonymousModuleKind => { - match self.get_nearest_normal_module_parent(module_.clone()) { - None => module_, - Some(new_module) => new_module, - } - } + if module_.is_normal() { + return module_; + } + match self.get_nearest_normal_module_parent(module_.clone()) { + None => module_, + Some(new_module) => new_module, } } @@ -1872,10 +1692,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { build_reduced_graph::populate_module_if_necessary(self, &module_); match module_.children.borrow().get(&name) { - Some(name_bindings) if name_bindings.defined_in_namespace(namespace) => { + Some(name_bindings) if name_bindings[namespace].defined() => { debug!("(resolving name in module) found node as child"); return Success((Target::new(module_.clone(), - name_bindings.clone(), + name_bindings[namespace].clone(), Shadowable::Never), false)); } @@ -1911,7 +1731,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let id = import_resolution.id(namespace); self.used_imports.insert((id, namespace)); self.record_import_use(id, name); - if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() { + if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() { self.used_crates.insert(kid); } return Success((target, true)); @@ -1926,8 +1746,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // FIXME (21114): In principle unclear `child` *has* to be lifted. let child = module_.external_module_children.borrow().get(&name).cloned(); if let Some(module) = child { - let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module)); - return Success((Target::new(module_, name_bindings, Shadowable::Never), + let name_binding = NameBinding::create_from_module(module); + return Success((Target::new(module_, name_binding, Shadowable::Never), false)); } } @@ -1951,7 +1771,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { build_reduced_graph::populate_module_if_necessary(self, &module_); for (_, child_node) in module_.children.borrow().iter() { - match child_node.get_module_if_available() { + match child_node.type_ns.module() { None => { // Continue. } @@ -2004,7 +1824,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module_to_string(&*orig_module)); } Some(name_bindings) => { - match (*name_bindings).get_module_if_available() { + match name_bindings.type_ns.module() { None => { debug!("!!! (with scope) didn't find module for `{}` in `{}`", name, @@ -2958,32 +2778,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Success((target, _)) => { debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}", name, - target.bindings.value_def.borrow()); - match *target.bindings.value_def.borrow() { + target.binding.borrow()); + match target.binding.def() { None => { panic!("resolved name in the value namespace to a set of name bindings \ with no def?!"); } - Some(def) => { - // For the two success cases, this lookup can be - // considered as not having a private component because - // the lookup happened only within the current module. - match def.def { - def @ DefVariant(..) | def @ DefStruct(..) => { - return FoundStructOrEnumVariant(def, LastMod(AllPublic)); - } - def @ DefConst(..) | def @ DefAssociatedConst(..) => { - return FoundConst(def, LastMod(AllPublic), name); - } - DefStatic(..) => { - resolve_error(self, span, ResolutionError::StaticVariableReference); - return BareIdentifierPatternUnresolved; - } - _ => { - return BareIdentifierPatternUnresolved; - } - } + // For the two success cases, this lookup can be + // considered as not having a private component because + // the lookup happened only within the current module. + Some(def @ DefVariant(..)) | Some(def @ DefStruct(..)) => { + return FoundStructOrEnumVariant(def, LastMod(AllPublic)); } + Some(def @ DefConst(..)) | Some(def @ DefAssociatedConst(..)) => { + return FoundConst(def, LastMod(AllPublic), name); + } + Some(DefStatic(..)) => { + resolve_error(self, span, ResolutionError::StaticVariableReference); + return BareIdentifierPatternUnresolved; + } + _ => return BareIdentifierPatternUnresolved } } @@ -3207,85 +3021,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Some(def); } - // FIXME #4952: Merge me with resolve_name_in_module? - fn resolve_definition_of_name_in_module(&mut self, - containing_module: Rc, - name: Name, - namespace: Namespace) - -> NameDefinition { - // First, search children. - build_reduced_graph::populate_module_if_necessary(self, &containing_module); - - match containing_module.children.borrow().get(&name) { - Some(child_name_bindings) => { - match child_name_bindings.def_for_namespace(namespace) { - Some(def) => { - // Found it. Stop the search here. - let p = child_name_bindings.defined_in_public_namespace(namespace); - let lp = if p { - LastMod(AllPublic) - } else { - LastMod(DependsOn(def.def_id())) - }; - return ChildNameDefinition(def, lp); - } - None => {} - } - } - None => {} - } - - // Next, search import resolutions. - match containing_module.import_resolutions.borrow().get(&name) { - Some(import_resolution) if import_resolution.is_public => { - if let Some(target) = (*import_resolution).target_for_namespace(namespace) { - match target.bindings.def_for_namespace(namespace) { - Some(def) => { - // Found it. - let id = import_resolution.id(namespace); - // track imports and extern crates as well - self.used_imports.insert((id, namespace)); - self.record_import_use(id, name); - match target.target_module.def_id.get() { - Some(DefId{krate: kid, ..}) => { - self.used_crates.insert(kid); - } - _ => {} - } - return ImportNameDefinition(def, LastMod(AllPublic)); - } - None => { - // This can happen with external impls, due to - // the imperfect way we read the metadata. - } - } - } - } - Some(..) | None => {} // Continue. - } - - // Finally, search through external children. - if namespace == TypeNS { - if let Some(module) = containing_module.external_module_children - .borrow() - .get(&name) - .cloned() { - if let Some(def_id) = module.def_id.get() { - // track used crates - self.used_crates.insert(def_id.krate); - let lp = if module.is_public { - LastMod(AllPublic) - } else { - LastMod(DependsOn(def_id)) - }; - return ChildNameDefinition(DefMod(def_id), lp); - } - } - } - - return NoNameDefinition; - } - // resolve a "module-relative" path, e.g. a::b::c fn resolve_module_relative_path(&mut self, span: Span, @@ -3328,18 +3063,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let name = segments.last().unwrap().identifier.name; - let def = match self.resolve_definition_of_name_in_module(containing_module.clone(), - name, - namespace) { - NoNameDefinition => { - // We failed to resolve the name. Report an error. - return None; - } - ChildNameDefinition(def, lp) | ImportNameDefinition(def, lp) => { + let def = match self.resolve_name_in_module(containing_module.clone(), + name, + namespace, + NameSearchType::PathSearch, + false) { + Success((Target { binding, .. }, _)) => { + let (def, lp) = binding.def_and_lp(); (def, last_private.or(lp)) } + _ => return None, }; - if let Some(DefId{krate: kid, ..}) = containing_module.def_id.get() { + if let Some(DefId{krate: kid, ..}) = containing_module.def_id() { self.used_crates.insert(kid); } return Some(def); @@ -3359,7 +3094,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .map(|ps| ps.identifier.name) .collect::>(); - let root_module = self.graph_root.get_module(); + let root_module = self.graph_root.clone(); let containing_module; let last_private; @@ -3394,14 +3129,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let name = segments.last().unwrap().identifier.name; - match self.resolve_definition_of_name_in_module(containing_module, name, namespace) { - NoNameDefinition => { - // We failed to resolve the name. Report an error. - return None; - } - ChildNameDefinition(def, lp) | ImportNameDefinition(def, lp) => { - return Some((def, last_private.or(lp))); + match self.resolve_name_in_module(containing_module, + name, + namespace, + NameSearchType::PathSearch, + false) { + Success((Target { binding, .. }, _)) => { + let (def, lp) = binding.def_and_lp(); + Some((def, last_private.or(lp))) } + _ => None, } } @@ -3449,7 +3186,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let module = self.current_module.clone(); match self.resolve_item_in_lexical_scope(module, name, namespace) { Success((target, _)) => { - match (*target.bindings).def_for_namespace(namespace) { + match target.binding.def() { None => { // This can happen if we were looking for a type and // found a module instead. Modules don't have defs. @@ -3520,7 +3257,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(_) => None, None => { match this.current_module.children.borrow().get(last_name) { - Some(child) => child.get_module_if_available(), + Some(child) => child.type_ns.module(), None => None, } } @@ -3586,7 +3323,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Look for a method in the current self type's impl module. if let Some(module) = get_module(self, path.span, &name_path) { if let Some(binding) = module.children.borrow().get(&name) { - if let Some(DefMethod(did)) = binding.def_for_namespace(ValueNS) { + if let Some(DefMethod(did)) = binding.value_ns.def() { if is_static_method(self, did) { return StaticMethod(path_names_to_string(&path, 0)); } @@ -3894,7 +3631,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { { for (_, child_names) in search_module.children.borrow().iter() { - let def = match child_names.def_for_namespace(TypeNS) { + let def = match child_names.type_ns.def() { Some(def) => def, None => continue, }; @@ -3914,7 +3651,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => continue, Some(target) => target, }; - let did = match target.bindings.def_for_namespace(TypeNS) { + let did = match target.binding.def() { Some(DefTrait(trait_def_id)) => trait_def_id, Some(..) | None => continue, }; @@ -3924,7 +3661,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.used_imports.insert((id, TypeNS)); let trait_name = self.get_trait_name(did); self.record_import_use(id, trait_name); - if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() { + if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() { self.used_crates.insert(kid); } } @@ -4125,7 +3862,7 @@ pub fn create_resolver<'a, 'tcx>(session: &'a Session, make_glob_map: MakeGlobMap, callback: Option bool>>) -> Resolver<'a, 'tcx> { - let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map); + let mut resolver = Resolver::new(session, ast_map, make_glob_map); resolver.callback = callback; diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 96fad16536cb8..3a6a5a031b6a1 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -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, - name: ast::Name, - namebindings: &NameBindings, - ns: Namespace) { - match namebindings.def_for_namespace(ns) { + fn add_export_of_namebinding(&mut self, + exports: &mut Vec, + 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); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9a21ec86685c1..4f67d6e2f7e79 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -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, - pub bindings: Rc, + pub binding: NameBinding, pub shadowable: Shadowable, } impl Target { pub fn new(target_module: Rc, - bindings: Rc, + 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, import_directive: &ImportDirective, name: Name, - name_bindings: Rc) { + 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); } } diff --git a/src/test/compile-fail/enum-and-module-in-same-scope.rs b/src/test/compile-fail/enum-and-module-in-same-scope.rs index f3d8fcf31d76c..67969616ca3c9 100644 --- a/src/test/compile-fail/enum-and-module-in-same-scope.rs +++ b/src/test/compile-fail/enum-and-module-in-same-scope.rs @@ -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() {} diff --git a/src/test/compile-fail/issue-21546.rs b/src/test/compile-fail/issue-21546.rs index bb1bcd4e8717d..535630e0824ca 100644 --- a/src/test/compile-fail/issue-21546.rs +++ b/src/test/compile-fail/issue-21546.rs @@ -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)]