From a8514d3ecca6bd404e2d7eff4deef31e3d00dad8 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 11 Jan 2016 21:19:29 +0000 Subject: [PATCH] resolve: use arena allocation instead of reference counting for `Module`s to fix memory leaks from Rc cycles --- mk/crates.mk | 2 +- src/librustc_resolve/build_reduced_graph.rs | 112 ++++---- src/librustc_resolve/lib.rs | 268 +++++++++++--------- src/librustc_resolve/record_exports.rs | 19 +- src/librustc_resolve/resolve_imports.rs | 104 ++++---- 5 files changed, 260 insertions(+), 245 deletions(-) diff --git a/mk/crates.mk b/mk/crates.mk index 2597c724da9..9d6215a51cc 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -103,7 +103,7 @@ DEPS_rustc_lint := rustc log syntax DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags DEPS_rustc_metadata := rustc rustc_front syntax rbml DEPS_rustc_mir := rustc rustc_front syntax -DEPS_rustc_resolve := rustc rustc_front log syntax +DEPS_rustc_resolve := arena rustc rustc_front log syntax DEPS_rustc_platform_intrinsics := rustc rustc_llvm DEPS_rustc_plugin := rustc rustc_metadata syntax DEPS_rustc_privacy := rustc rustc_front log syntax diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 8ed47300a17..2e713a2f50e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -21,7 +21,7 @@ use Module; use Namespace::{TypeNS, ValueNS}; use NameBindings; use {names_to_string, module_to_string}; -use ParentLink::{self, ModuleParentLink, BlockParentLink}; +use ParentLink::{ModuleParentLink, BlockParentLink}; use Resolver; use resolve_imports::Shadowable; use {resolve_error, resolve_struct_error, ResolutionError}; @@ -52,7 +52,6 @@ use rustc_front::intravisit::{self, Visitor}; use std::mem::replace; use std::ops::{Deref, DerefMut}; -use std::rc::Rc; // Specifies how duplicates should be handled when adding a child item if // another item exists with the same name in some namespace. @@ -86,7 +85,7 @@ 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 mut visitor = BuildReducedGraphVisitor { - parent: self.graph_root.clone(), + parent: self.graph_root, builder: self, }; intravisit::walk_crate(&mut visitor, krate); @@ -97,12 +96,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Returns the child's corresponding name bindings. fn add_child(&self, name: Name, - parent: &Rc, + parent: Module<'b>, duplicate_checking_mode: DuplicateCheckingMode, // For printing errors sp: Span) - -> NameBindings { - self.check_for_conflicts_between_external_crates_and_items(&**parent, name, sp); + -> NameBindings<'b> { + 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(); @@ -178,12 +177,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { return false; } - fn get_parent_link(&mut self, parent: &Rc, name: Name) -> ParentLink { - ModuleParentLink(Rc::downgrade(parent), name) - } - /// Constructs the reduced graph for one item. - fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc) -> Rc { + fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> Module<'b> { let name = item.name; let sp = item.span; let is_public = item.vis == hir::Public; @@ -238,7 +233,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } let subclass = SingleImport(binding, source_name); - self.build_import_directive(&**parent, + self.build_import_directive(parent, module_path, subclass, view_path.span, @@ -288,7 +283,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { (module_path.to_vec(), name, rename) } }; - self.build_import_directive(&**parent, + self.build_import_directive(parent, module_path, SingleImport(rename, name), source_item.span, @@ -298,7 +293,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } } ViewPathGlob(_) => { - self.build_import_directive(&**parent, + self.build_import_directive(parent, module_path, GlobImport, view_path.span, @@ -307,7 +302,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { shadowable); } } - parent.clone() + parent } ItemExternCrate(_) => { @@ -319,32 +314,32 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { index: CRATE_DEF_INDEX, }; self.external_exports.insert(def_id); - let parent_link = ModuleParentLink(Rc::downgrade(parent), name); + let parent_link = ModuleParentLink(parent, name); let def = DefMod(def_id); - let external_module = Module::new(parent_link, Some(def), false, true); + let external_module = self.new_module(parent_link, Some(def), false, true); debug!("(build reduced graph for item) found extern `{}`", module_to_string(&*external_module)); - self.check_for_conflicts_for_external_crate(&parent, name, sp); + self.check_for_conflicts_for_external_crate(parent, name, sp); parent.external_module_children .borrow_mut() - .insert(name, external_module.clone()); + .insert(name, external_module); self.build_reduced_graph_for_external_crate(&external_module); } - parent.clone() + parent } ItemMod(..) => { let name_bindings = self.add_child(name, parent, ForbidDuplicateTypes, sp); - let parent_link = self.get_parent_link(parent, name); + let parent_link = ModuleParentLink(parent, name); let def = DefMod(self.ast_map.local_def_id(item.id)); - let module = Module::new(parent_link, Some(def), false, is_public); + let module = self.new_module(parent_link, Some(def), false, is_public); name_bindings.define_module(module.clone(), sp); module } - ItemForeignMod(..) => parent.clone(), + ItemForeignMod(..) => parent, // These items live in the value namespace. ItemStatic(_, m, _) => { @@ -354,19 +349,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { name_bindings.define_value(DefStatic(self.ast_map.local_def_id(item.id), mutbl), sp, modifiers); - parent.clone() + parent } ItemConst(_, _) => { self.add_child(name, parent, ForbidDuplicateValues, sp) .define_value(DefConst(self.ast_map.local_def_id(item.id)), sp, modifiers); - parent.clone() + parent } ItemFn(_, _, _, _, _, _) => { let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp); let def = DefFn(self.ast_map.local_def_id(item.id), false); name_bindings.define_value(def, sp, modifiers); - parent.clone() + parent } // These items live in the type namespace. @@ -376,11 +371,11 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { ForbidDuplicateTypes, sp); - let parent_link = self.get_parent_link(parent, name); + let parent_link = ModuleParentLink(parent, name); let def = DefTy(self.ast_map.local_def_id(item.id), false); - let module = Module::new(parent_link, Some(def), false, is_public); + let module = self.new_module(parent_link, Some(def), false, is_public); name_bindings.define_module(module, sp); - parent.clone() + parent } ItemEnum(ref enum_definition, _) => { @@ -389,9 +384,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { ForbidDuplicateTypes, sp); - let parent_link = self.get_parent_link(parent, name); + let parent_link = ModuleParentLink(parent, name); let def = DefTy(self.ast_map.local_def_id(item.id), true); - let module = Module::new(parent_link, Some(def), false, is_public); + let module = self.new_module(parent_link, Some(def), false, is_public); name_bindings.define_module(module.clone(), sp); let variant_modifiers = if is_public { @@ -404,7 +399,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.build_reduced_graph_for_variant(variant, item_def_id, &module, variant_modifiers); } - parent.clone() + parent } // These items live in both the type and value namespaces. @@ -444,11 +439,11 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let item_def_id = self.ast_map.local_def_id(item.id); self.structs.insert(item_def_id, named_fields); - parent.clone() + parent } ItemDefaultImpl(_, _) | - ItemImpl(..) => parent.clone(), + ItemImpl(..) => parent, ItemTrait(_, _, _, ref items) => { let name_bindings = self.add_child(name, @@ -459,9 +454,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { 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); + let parent_link = ModuleParentLink(parent, name); let def = DefTrait(def_id); - let module_parent = Module::new(parent_link, Some(def), false, is_public); + let module_parent = self.new_module(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. @@ -494,7 +489,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.trait_item_map.insert((trait_item.name, def_id), trait_item_def_id); } - parent.clone() + parent } } } @@ -504,7 +499,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { fn build_reduced_graph_for_variant(&mut self, variant: &Variant, item_id: DefId, - parent: &Rc, + parent: Module<'b>, variant_modifiers: DefModifiers) { let name = variant.node.name; let is_exported = if variant.node.data.is_struct() { @@ -534,7 +529,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, foreign_item: &ForeignItem, - parent: &Rc) { + parent: Module<'b>) { let name = foreign_item.name; let is_public = foreign_item.vis == hir::Public; let modifiers = if is_public { @@ -555,7 +550,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { name_bindings.define_value(def, foreign_item.span, modifiers); } - fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc) -> Rc { + fn build_reduced_graph_for_block(&mut self, block: &Block, parent: Module<'b>) -> Module<'b> { if self.block_needs_anonymous_module(block) { let block_id = block.id; @@ -563,22 +558,22 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { {}", block_id); - 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()); + let parent_link = BlockParentLink(parent, block_id); + let new_module = self.new_module(parent_link, None, false, false); + parent.anonymous_children.borrow_mut().insert(block_id, new_module); new_module } else { - parent.clone() + parent } } fn handle_external_def(&mut self, def: Def, vis: Visibility, - child_name_bindings: &NameBindings, + child_name_bindings: &NameBindings<'b>, final_ident: &str, name: Name, - new_parent: &Rc) { + new_parent: Module<'b>) { debug!("(building reduced graph for external crate) building external def {}, priv {:?}", final_ident, vis); @@ -609,8 +604,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { 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); + let parent_link = ModuleParentLink(new_parent, name); + let module = self.new_module(parent_link, Some(def), true, is_public); child_name_bindings.define_module(module, DUMMY_SP); } } @@ -681,8 +676,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } // Define a module if necessary. - let parent_link = self.get_parent_link(new_parent, name); - let module = Module::new(parent_link, Some(def), true, is_public); + let parent_link = ModuleParentLink(new_parent, name); + let module = self.new_module(parent_link, Some(def), true, is_public); child_name_bindings.define_module(module, DUMMY_SP); } DefTy(..) | DefAssociatedTy(..) => { @@ -728,7 +723,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_def(&mut self, - root: &Rc, + root: Module<'b>, xcdef: ChildItem) { match xcdef.def { DlDef(def) => { @@ -766,9 +761,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } /// Builds the reduced graph rooted at the given external module. - fn populate_external_module(&mut self, module: &Rc) { + fn populate_external_module(&mut self, module: Module<'b>) { debug!("(populating external module) attempting to populate {}", - module_to_string(&**module)); + module_to_string(module)); let def_id = match module.def_id() { None => { @@ -788,7 +783,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Ensures that the reduced graph rooted at the given external module /// is built, building it if it is not. - fn populate_module_if_necessary(&mut self, module: &Rc) { + fn populate_module_if_necessary(&mut self, module: Module<'b>) { if !module.populated.get() { self.populate_external_module(module) } @@ -797,7 +792,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Builds the reduced graph rooted at the 'use' directive for an external /// crate. - fn build_reduced_graph_for_external_crate(&mut self, root: &Rc) { + fn build_reduced_graph_for_external_crate(&mut self, root: Module<'b>) { let root_cnum = root.def_id().unwrap().krate; for child in self.session.cstore.crate_top_level_items(root_cnum) { self.build_reduced_graph_for_external_crate_def(root, child); @@ -806,7 +801,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Creates and adds an import directive to the given module. fn build_import_directive(&mut self, - module_: &Module, + module_: Module<'b>, module_path: Vec, subclass: ImportDirectiveSubclass, span: Span, @@ -866,7 +861,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> { builder: GraphBuilder<'a, 'b, 'tcx>, - parent: Rc, + parent: Module<'b>, } impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { @@ -897,6 +892,7 @@ pub fn build_reduced_graph(resolver: &mut Resolver, krate: &hir::Crate) { GraphBuilder { resolver: resolver }.build_reduced_graph(krate); } -pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc) { +pub fn populate_module_if_necessary<'a, 'tcx>(resolver: &mut Resolver<'a, 'tcx>, + module: Module<'a>) { GraphBuilder { resolver: resolver }.populate_module_if_necessary(module); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c7031f72af4..9857e83bd62 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -26,6 +26,7 @@ extern crate log; #[macro_use] extern crate syntax; +extern crate arena; #[macro_use] #[no_link] extern crate rustc_bitflags; @@ -90,7 +91,7 @@ use std::collections::{HashMap, HashSet}; use std::cell::{Cell, RefCell}; use std::fmt; use std::mem::replace; -use std::rc::{Rc, Weak}; +use std::rc::Rc; use resolve_imports::{Target, ImportDirective, ImportResolutionPerNamespace}; use resolve_imports::Shadowable; @@ -576,7 +577,7 @@ pub enum Namespace { /// a particular namespace. The result is either definitely-resolved, /// definitely- unresolved, or unknown. #[derive(Clone)] -enum NamespaceResult { +enum NamespaceResult<'a> { /// Means that resolve hasn't gathered enough information yet to determine /// whether the name is bound in this namespace. (That is, it hasn't /// resolved all `use` directives yet.) @@ -586,10 +587,10 @@ enum NamespaceResult { UnboundResult, /// Means that resolve has determined that the name is bound in the Module /// argument, and specified by the NameBinding argument. - BoundResult(Rc, NameBinding), + BoundResult(Module<'a>, NameBinding<'a>), } -impl NamespaceResult { +impl<'a> NamespaceResult<'a> { fn is_unknown(&self) -> bool { match *self { UnknownResult => true, @@ -766,9 +767,9 @@ enum UseLexicalScopeFlag { UseLexicalScope, } -enum ModulePrefixResult { +enum ModulePrefixResult<'a> { NoPrefixFound, - PrefixFound(Rc, usize), + PrefixFound(Module<'a>, usize), } #[derive(Copy, Clone)] @@ -830,24 +831,24 @@ impl LocalDef { /// The link from a module up to its nearest parent node. #[derive(Clone,Debug)] -enum ParentLink { +enum ParentLink<'a> { NoParentLink, - ModuleParentLink(Weak, Name), - BlockParentLink(Weak, NodeId), + ModuleParentLink(Module<'a>, Name), + BlockParentLink(Module<'a>, NodeId), } /// One node in the tree of modules. -pub struct Module { - parent_link: ParentLink, +pub struct ModuleS<'a> { + parent_link: ParentLink<'a>, def: Cell>, is_public: bool, - children: RefCell>, + children: RefCell>>, imports: RefCell>, // The external module children of this node that were declared with // `extern crate`. - external_module_children: RefCell>>, + external_module_children: RefCell>>, // The anonymous children of this node. Anonymous children are pseudo- // modules that are implicitly created around items contained within @@ -863,10 +864,10 @@ pub struct Module { // // There will be an anonymous module created around `g` with the ID of the // entry block for `f`. - anonymous_children: RefCell>>, + anonymous_children: RefCell>>, // The status of resolving each import in this module. - import_resolutions: RefCell>, + import_resolutions: RefCell>>, // The number of unresolved globs that this module exports. glob_count: Cell, @@ -886,13 +887,11 @@ pub struct Module { populated: Cell, } -impl Module { - fn new(parent_link: ParentLink, - def: Option, - external: bool, - is_public: bool) - -> Rc { - Rc::new(Module { +pub type Module<'a> = &'a ModuleS<'a>; + +impl<'a> ModuleS<'a> { + fn new(parent_link: ParentLink<'a>, def: Option, external: bool, is_public: bool) -> Self { + ModuleS { parent_link: parent_link, def: Cell::new(def), is_public: is_public, @@ -906,7 +905,7 @@ impl Module { pub_glob_count: Cell::new(0), resolved_import_count: Cell::new(0), populated: Cell::new(!external), - }) + } } fn def_id(&self) -> Option { @@ -935,9 +934,7 @@ impl Module { self.imports.borrow().len() == self.resolved_import_count.get() } } -} -impl Module { pub fn inc_glob_count(&self) { self.glob_count.set(self.glob_count.get() + 1); } @@ -961,7 +958,7 @@ impl Module { } } -impl fmt::Debug for Module { +impl<'a> fmt::Debug for ModuleS<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}, {}", @@ -989,20 +986,20 @@ bitflags! { // Records a possibly-private value, type, or module definition. #[derive(Debug)] -struct NsDef { +struct NsDef<'a> { modifiers: DefModifiers, // see note in ImportResolutionPerNamespace about how to use this - def_or_module: DefOrModule, + def_or_module: DefOrModule<'a>, span: Option, } #[derive(Debug)] -enum DefOrModule { +enum DefOrModule<'a> { Def(Def), - Module(Rc), + Module(Module<'a>), } -impl NsDef { - fn create_from_module(module: Rc, span: Option) -> Self { +impl<'a> NsDef<'a> { + fn create_from_module(module: Module<'a>, span: Option) -> Self { let modifiers = if module.is_public { DefModifiers::PUBLIC } else { @@ -1016,9 +1013,9 @@ impl NsDef { NsDef { modifiers: modifiers, def_or_module: DefOrModule::Def(def), span: span } } - fn module(&self) -> Option> { + fn module(&self) -> Option> { match self.def_or_module { - DefOrModule::Module(ref module) => Some(module.clone()), + DefOrModule::Module(ref module) => Some(module), DefOrModule::Def(_) => None, } } @@ -1033,18 +1030,18 @@ impl NsDef { // Records at most one definition that a name in a namespace is bound to #[derive(Clone,Debug)] -pub struct NameBinding(Rc>>); +pub struct NameBinding<'a>(Rc>>>); -impl NameBinding { +impl<'a> NameBinding<'a> { fn new() -> Self { NameBinding(Rc::new(RefCell::new(None))) } - fn create_from_module(module: Rc) -> Self { + fn create_from_module(module: Module<'a>) -> Self { NameBinding(Rc::new(RefCell::new(Some(NsDef::create_from_module(module, None))))) } - fn set(&self, ns_def: NsDef) { + fn set(&self, ns_def: NsDef<'a>) { *self.0.borrow_mut() = Some(ns_def); } @@ -1054,7 +1051,7 @@ impl NameBinding { } } - fn borrow(&self) -> ::std::cell::Ref> { + fn borrow(&self) -> ::std::cell::Ref>> { self.0.borrow() } @@ -1062,7 +1059,7 @@ impl NameBinding { fn def(&self) -> Option { self.borrow().as_ref().and_then(NsDef::def) } - fn module(&self) -> Option> { + fn module(&self) -> Option> { self.borrow().as_ref().and_then(NsDef::module) } fn span(&self) -> Option { @@ -1093,20 +1090,20 @@ impl NameBinding { // 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. +pub struct NameBindings<'a> { + type_ns: NameBinding<'a>, // < Meaning in type namespace. + value_ns: NameBinding<'a>, // < Meaning in value namespace. } -impl ::std::ops::Index for NameBindings { - type Output = NameBinding; - fn index(&self, namespace: Namespace) -> &NameBinding { +impl<'a> ::std::ops::Index for NameBindings<'a> { + type Output = NameBinding<'a>; + fn index(&self, namespace: Namespace) -> &NameBinding<'a> { match namespace { TypeNS => &self.type_ns, ValueNS => &self.value_ns } } } -impl NameBindings { - fn new() -> NameBindings { +impl<'a> NameBindings<'a> { + fn new() -> Self { NameBindings { type_ns: NameBinding::new(), value_ns: NameBinding::new(), @@ -1114,7 +1111,7 @@ impl NameBindings { } /// Creates a new module in this set of name bindings. - fn define_module(&self, module: Rc, sp: Span) { + fn define_module(&self, module: Module<'a>, sp: Span) { self.type_ns.set(NsDef::create_from_module(module, Some(sp))); } @@ -1170,7 +1167,7 @@ pub struct Resolver<'a, 'tcx: 'a> { ast_map: &'a hir_map::Map<'tcx>, - graph_root: Rc, + graph_root: Module<'a>, trait_item_map: FnvHashMap<(Name, DefId), DefId>, @@ -1180,7 +1177,7 @@ pub struct Resolver<'a, 'tcx: 'a> { unresolved_imports: usize, // The module that represents the current item scope. - current_module: Rc, + current_module: Module<'a>, // The current set of local scopes, for values. // FIXME #4948: Reuse ribs to avoid allocation. @@ -1226,6 +1223,12 @@ pub struct Resolver<'a, 'tcx: 'a> { // The intention is that the callback modifies this flag. // Once set, the resolver falls out of the walk, preserving the ribs. resolved: bool, + + arenas: &'a ResolverArenas<'a>, +} + +pub struct ResolverArenas<'a> { + modules: arena::TypedArena>, } #[derive(PartialEq)] @@ -1237,10 +1240,12 @@ enum FallbackChecks { impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>, - make_glob_map: MakeGlobMap) + make_glob_map: MakeGlobMap, + arenas: &'a ResolverArenas<'a>) -> Resolver<'a, 'tcx> { let root_def_id = ast_map.local_def_id(CRATE_NODE_ID); - let graph_root = Module::new(NoParentLink, Some(DefMod(root_def_id)), false, true); + let graph_root = ModuleS::new(NoParentLink, Some(DefMod(root_def_id)), false, true); + let graph_root = arenas.modules.alloc(graph_root); Resolver { session: session, @@ -1249,7 +1254,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // The outermost module has def ID 0; this is not reflected in the // AST. - graph_root: graph_root.clone(), + graph_root: graph_root, trait_item_map: FnvHashMap(), structs: FnvHashMap(), @@ -1281,9 +1286,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { callback: None, resolved: false, + + arenas: arenas, } } + fn arenas() -> ResolverArenas<'a> { + ResolverArenas { + modules: arena::TypedArena::new(), + } + } + + fn new_module(&self, + parent_link: ParentLink<'a>, + def: Option, + external: bool, + is_public: bool) -> Module<'a> { + self.arenas.modules.alloc(ModuleS::new(parent_link, def, external, is_public)) + } + #[inline] fn record_import_use(&mut self, import_id: NodeId, name: Name) { if !self.make_glob_map { @@ -1308,7 +1329,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } /// Check that an external crate doesn't collide with items or other external crates. - fn check_for_conflicts_for_external_crate(&self, module: &Module, name: Name, span: Span) { + fn check_for_conflicts_for_external_crate(&self, module: Module<'a>, name: Name, span: Span) { if module.external_module_children.borrow().contains_key(&name) { span_err!(self.session, span, @@ -1328,7 +1349,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Checks that the names of items don't collide with external crates. fn check_for_conflicts_between_external_crates_and_items(&self, - module: &Module, + module: Module<'a>, name: Name, span: Span) { if module.external_module_children.borrow().contains_key(&name) { @@ -1338,19 +1359,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Resolves the given module path from the given root `module_`. fn resolve_module_path_from_root(&mut self, - module_: Rc, + module_: Module<'a>, module_path: &[Name], index: usize, span: Span, name_search_type: NameSearchType, lp: LastPrivate) - -> ResolveResult<(Rc, LastPrivate)> { - fn search_parent_externals(needle: Name, module: &Rc) -> Option> { + -> ResolveResult<(Module<'a>, LastPrivate)> { + fn search_parent_externals<'a>(needle: Name, module: Module<'a>) + -> Option> { match module.external_module_children.borrow().get(&needle) { - Some(_) => Some(module.clone()), + Some(_) => Some(module), None => match module.parent_link { ModuleParentLink(ref parent, _) => { - search_parent_externals(needle, &parent.upgrade().unwrap()) + search_parent_externals(needle, parent) } _ => None, }, @@ -1367,14 +1389,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // modules as we go. while index < module_path_len { let name = module_path[index]; - match self.resolve_name_in_module(search_module.clone(), + match self.resolve_name_in_module(search_module, name, TypeNS, name_search_type, false) { Failed(None) => { let segment_name = name.as_str(); - let module_name = module_to_string(&*search_module); + let module_name = module_to_string(search_module); let mut span = span; let msg = if "???" == &module_name[..] { span.hi = span.lo + Pos::from_usize(segment_name.len()); @@ -1445,12 +1467,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// On success, returns the resolved module, and the closest *private* /// module found to the destination when resolving this path. fn resolve_module_path(&mut self, - module_: Rc, + module_: Module<'a>, module_path: &[Name], use_lexical_scope: UseLexicalScopeFlag, span: Span, name_search_type: NameSearchType) - -> ResolveResult<(Rc, LastPrivate)> { + -> ResolveResult<(Module<'a>, LastPrivate)> { let module_path_len = module_path.len(); assert!(module_path_len > 0); @@ -1459,7 +1481,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module_to_string(&*module_)); // Resolve the module prefix, if any. - let module_prefix_result = self.resolve_module_prefix(module_.clone(), module_path); + let module_prefix_result = self.resolve_module_prefix(module_, module_path); let search_module; let start_index; @@ -1495,7 +1517,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.clone(); + search_module = self.graph_root; start_index = 0; last_private = LastMod(AllPublic); } @@ -1519,7 +1541,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } Success(PrefixFound(ref containing_module, index)) => { - search_module = containing_module.clone(); + search_module = containing_module; start_index = index; last_private = LastMod(DependsOn(containing_module.def_id() .unwrap())); @@ -1537,11 +1559,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Invariant: This must only be called during main resolution, not during /// import resolution. fn resolve_item_in_lexical_scope(&mut self, - module_: Rc, + module_: Module<'a>, name: Name, namespace: Namespace, record_used: bool) - -> ResolveResult<(Target, bool)> { + -> ResolveResult<(Target<'a>, bool)> { debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`", name, namespace, @@ -1554,7 +1576,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match module_.children.borrow().get(&name) { Some(name_bindings) if name_bindings[namespace].defined() => { debug!("top name bindings succeeded"); - return Success((Target::new(module_.clone(), + return Success((Target::new(module_, name_bindings[namespace].clone(), Shadowable::Never), false)); @@ -1594,9 +1616,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Search for external modules. if namespace == TypeNS { - // 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 children = module_.external_module_children.borrow(); + if let Some(module) = children.get(&name) { let name_binding = NameBinding::create_from_module(module); debug!("lower name bindings succeeded"); return Success((Target::new(module_, name_binding, Shadowable::Never), @@ -1608,7 +1629,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut search_module = module_; loop { // Go to the next parent. - match search_module.parent_link.clone() { + match search_module.parent_link { NoParentLink => { // No more parents. This module was unresolved. debug!("(resolving item in lexical scope) unresolved module"); @@ -1621,16 +1642,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { searching through module parents"); return Failed(None); } else { - search_module = parent_module_node.upgrade().unwrap(); + search_module = parent_module_node; } } - BlockParentLink(ref parent_module_node, _) => { - search_module = parent_module_node.upgrade().unwrap(); + BlockParentLink(parent_module_node, _) => { + search_module = parent_module_node; } } // Resolve the name in the parent module. - match self.resolve_name_in_module(search_module.clone(), + match self.resolve_name_in_module(search_module, name, namespace, PathSearch, @@ -1657,9 +1678,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Resolves a module name in the current lexical scope. fn resolve_module_in_lexical_scope(&mut self, - module_: Rc, + module_: Module<'a>, name: Name) - -> ResolveResult> { + -> ResolveResult> { // If this module is an anonymous module, resolve the item in the // lexical scope. Otherwise, resolve the item from the crate root. let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS, true); @@ -1685,14 +1706,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } /// Returns the nearest normal module parent of the given module. - fn get_nearest_normal_module_parent(&mut self, module_: Rc) -> Option> { + fn get_nearest_normal_module_parent(&mut self, module_: Module<'a>) -> Option> { let mut module_ = module_; loop { - match module_.parent_link.clone() { + match module_.parent_link { NoParentLink => return None, ModuleParentLink(new_module, _) | BlockParentLink(new_module, _) => { - let new_module = new_module.upgrade().unwrap(); + let new_module = new_module; if new_module.is_normal() { return Some(new_module); } @@ -1704,11 +1725,11 @@ 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 { + fn get_nearest_normal_module_parent_or_self(&mut self, module_: Module<'a>) -> Module<'a> { if module_.is_normal() { return module_; } - match self.get_nearest_normal_module_parent(module_.clone()) { + match self.get_nearest_normal_module_parent(module_) { None => module_, Some(new_module) => new_module, } @@ -1718,9 +1739,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// (b) some chain of `super::`. /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) * fn resolve_module_prefix(&mut self, - module_: Rc, + module_: Module<'a>, module_path: &[Name]) - -> ResolveResult { + -> ResolveResult> { // Start at the current module if we see `self` or `super`, or at the // top of the crate otherwise. let mut i = match &*module_path[0].as_str() { @@ -1756,12 +1777,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// The boolean returned on success is an indicator of whether this lookup /// passed through a public re-export proxy. fn resolve_name_in_module(&mut self, - module_: Rc, + module_: Module<'a>, name: Name, namespace: Namespace, name_search_type: NameSearchType, allow_private_imports: bool) - -> ResolveResult<(Target, bool)> { + -> ResolveResult<(Target<'a>, bool)> { debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(&*module_)); @@ -1769,10 +1790,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // First, check the direct children of the module. build_reduced_graph::populate_module_if_necessary(self, &module_); - match module_.children.borrow().get(&name) { + let children = module_.children.borrow(); + match children.get(&name) { Some(name_bindings) if name_bindings[namespace].defined() => { debug!("(resolving name in module) found node as child"); - return Success((Target::new(module_.clone(), + return Success((Target::new(module_, name_bindings[namespace].clone(), Shadowable::Never), false)); @@ -1791,7 +1813,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // Check the list of resolved imports. - match module_.import_resolutions.borrow().get(&name) { + let children = module_.import_resolutions.borrow(); + match children.get(&name) { Some(import_resolution) if allow_private_imports || import_resolution[namespace].is_public => { @@ -1823,9 +1846,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Finally, search through external children. if namespace == TypeNS { - // 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 children = module_.external_module_children.borrow(); + if let Some(module) = children.get(&name) { let name_binding = NameBinding::create_from_module(module); return Success((Target::new(module_, name_binding, Shadowable::Never), false)); @@ -1837,7 +1859,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Failed(None); } - fn report_unresolved_imports(&mut self, module_: Rc) { + fn report_unresolved_imports(&mut self, module_: Module<'a>) { let index = module_.resolved_import_count.get(); let imports = module_.imports.borrow(); let import_count = imports.len(); @@ -1862,7 +1884,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } for (_, module_) in module_.anonymous_children.borrow().iter() { - self.report_unresolved_imports(module_.clone()); + self.report_unresolved_imports(module_); } } @@ -1887,7 +1909,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn with_scope(&mut self, name: Option, f: F) where F: FnOnce(&mut Resolver) { - let orig_module = self.current_module.clone(); + let orig_module = self.current_module; // Move down in the graph. match name { @@ -2475,14 +2497,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.value_ribs.push(Rib::new(NormalRibKind)); // Move down in the graph, if there's an anonymous module rooted here. - let orig_module = self.current_module.clone(); + let orig_module = self.current_module; match orig_module.anonymous_children.borrow().get(&block.id) { None => { // Nothing to do. } Some(anonymous_module) => { debug!("(resolving block) found anonymous module, moving down"); - self.current_module = anonymous_module.clone(); + self.current_module = anonymous_module; } } @@ -2871,7 +2893,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { name: Name, span: Span) -> BareIdentifierPatternResolution { - let module = self.current_module.clone(); + let module = self.current_module; match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) { Success((target, _)) => { debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}", @@ -3135,7 +3157,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let containing_module; let last_private; - let current_module = self.current_module.clone(); + let current_module = self.current_module; match self.resolve_module_path(current_module, &module_path[..], UseLexicalScope, @@ -3162,7 +3184,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let name = segments.last().unwrap().identifier.name; - let def = match self.resolve_name_in_module(containing_module.clone(), + let def = match self.resolve_name_in_module(containing_module, name, namespace, NameSearchType::PathSearch, @@ -3193,7 +3215,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .map(|ps| ps.identifier.name) .collect::>(); - let root_module = self.graph_root.clone(); + let root_module = self.graph_root; let containing_module; let last_private; @@ -3283,7 +3305,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { record_used: bool) -> Option { // Check the items. - let module = self.current_module.clone(); + let module = self.current_module; match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) { Success((target, _)) => { match target.binding.def() { @@ -3345,11 +3367,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn get_module(this: &mut Resolver, - span: Span, - name_path: &[ast::Name]) - -> Option> { - let root = this.current_module.clone(); + fn get_module<'a, 'tcx>(this: &mut Resolver<'a, 'tcx>, + span: Span, + name_path: &[ast::Name]) + -> Option> { + let root = this.current_module; let last_name = name_path.last().unwrap(); if name_path.len() == 1 { @@ -3603,7 +3625,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let name_path = path.segments.iter() .map(|seg| seg.identifier.name) .collect::>(); - let current_module = self.current_module.clone(); + let current_module = self.current_module; match self.resolve_module_path(current_module, &name_path[..], @@ -3725,7 +3747,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let mut found_traits = Vec::new(); - let mut search_module = self.current_module.clone(); + let mut search_module = self.current_module; loop { // Look for the current trait. match self.current_trait_ref { @@ -3778,10 +3800,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - match search_module.parent_link.clone() { + match search_module.parent_link { NoParentLink | ModuleParentLink(..) => break, BlockParentLink(parent_module, _) => { - search_module = parent_module.upgrade().unwrap(); + search_module = parent_module; } } } @@ -3828,7 +3850,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // #[allow(dead_code)] // useful for debugging - fn dump_module(&mut self, module_: Rc) { + fn dump_module(&mut self, module_: Module<'a>) { debug!("Dump of module `{}`:", module_to_string(&*module_)); debug!("Children:"); @@ -3891,20 +3913,20 @@ fn path_names_to_string(path: &Path, depth: usize) -> String { } /// A somewhat inefficient routine to obtain the name of a module. -fn module_to_string(module: &Module) -> String { +fn module_to_string<'a>(module: Module<'a>) -> String { let mut names = Vec::new(); - fn collect_mod(names: &mut Vec, module: &Module) { + fn collect_mod<'a>(names: &mut Vec, module: Module<'a>) { match module.parent_link { NoParentLink => {} ModuleParentLink(ref module, name) => { names.push(name); - collect_mod(names, &*module.upgrade().unwrap()); + collect_mod(names, module); } BlockParentLink(ref module, _) => { // danger, shouldn't be ident? names.push(special_idents::opaque.name); - collect_mod(names, &*module.upgrade().unwrap()); + collect_mod(names, module); } } } @@ -3946,7 +3968,8 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, make_glob_map: MakeGlobMap) -> CrateMap { let krate = ast_map.krate(); - let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, None); + let arenas = Resolver::arenas(); + let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas, None); resolver.resolve_crate(krate); @@ -3978,9 +4001,10 @@ pub fn create_resolver<'a, 'tcx>(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>, krate: &'a Crate, make_glob_map: MakeGlobMap, + arenas: &'a ResolverArenas<'a>, callback: Option bool>>) -> Resolver<'a, 'tcx> { - let mut resolver = Resolver::new(session, ast_map, make_glob_map); + let mut resolver = Resolver::new(session, ast_map, make_glob_map, arenas); resolver.callback = callback; diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 59cf83e91d2..13f4348f795 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -28,7 +28,6 @@ use rustc::middle::def::Export; use syntax::ast; use std::ops::{Deref, DerefMut}; -use std::rc::Rc; struct ExportRecorder<'a, 'b: 'a, 'tcx: 'b> { resolver: &'a mut Resolver<'b, 'tcx>, @@ -50,7 +49,7 @@ impl<'a, 'b, 'tcx:'b> DerefMut for ExportRecorder<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { - fn record_exports_for_module_subtree(&mut self, module_: Rc) { + fn record_exports_for_module_subtree(&mut self, module_: Module<'b>) { // If this isn't a local krate, then bail out. We don't need to record // exports for nonlocal crates. @@ -59,23 +58,23 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { // OK. Continue. debug!("(recording exports for module subtree) recording exports for local \ module `{}`", - module_to_string(&*module_)); + module_to_string(module_)); } None => { // Record exports for the root module. debug!("(recording exports for module subtree) recording exports for root module \ `{}`", - module_to_string(&*module_)); + module_to_string(module_)); } Some(_) => { // Bail out. debug!("(recording exports for module subtree) not recording exports for `{}`", - module_to_string(&*module_)); + module_to_string(module_)); return; } } - self.record_exports_for_module(&*module_); + self.record_exports_for_module(module_); build_reduced_graph::populate_module_if_necessary(self.resolver, &module_); for (_, child_name_bindings) in module_.children.borrow().iter() { @@ -90,11 +89,11 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { } for (_, child_module) in module_.anonymous_children.borrow().iter() { - self.record_exports_for_module_subtree(child_module.clone()); + self.record_exports_for_module_subtree(child_module); } } - fn record_exports_for_module(&mut self, module_: &Module) { + fn record_exports_for_module(&mut self, module_: Module<'b>) { let mut exports = Vec::new(); self.add_exports_for_module(&mut exports, module_); @@ -128,7 +127,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { } } - fn add_exports_for_module(&mut self, exports: &mut Vec, module_: &Module) { + fn add_exports_for_module(&mut self, exports: &mut Vec, module_: Module<'b>) { for (name, import_resolution) in module_.import_resolutions.borrow().iter() { let xs = [TypeNS, ValueNS]; for &ns in &xs { @@ -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.clone(); + let root_module = recorder.graph_root; 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 40bf55efde6..53d1b888d8e 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -36,7 +36,6 @@ use syntax::codemap::Span; use syntax::util::lev_distance::find_best_match_for_name; use std::mem::replace; -use std::rc::Rc; /// Contains data for specific types of import directives. #[derive(Copy, Clone,Debug)] @@ -84,17 +83,15 @@ impl ImportDirective { /// The item that an import resolves to. #[derive(Clone,Debug)] -pub struct Target { - pub target_module: Rc, - pub binding: NameBinding, +pub struct Target<'a> { + pub target_module: Module<'a>, + pub binding: NameBinding<'a>, pub shadowable: Shadowable, } -impl Target { - pub fn new(target_module: Rc, - binding: NameBinding, - shadowable: Shadowable) - -> Target { +impl<'a> Target<'a> { + pub fn new(target_module: Module<'a>, binding: NameBinding<'a>, shadowable: Shadowable) + -> Self { Target { target_module: target_module, binding: binding, @@ -109,44 +106,44 @@ impl Target { /// and for each namespace, it records the `use` directive importing the name in the namespace /// and the `Target` to which the name in the namespace resolves (if applicable). /// Different `use` directives may import the same name in different namespaces. -pub struct ImportResolutionPerNamespace { +pub struct ImportResolutionPerNamespace<'a> { // When outstanding_references reaches zero, outside modules can count on the targets being // correct. Before then, all bets are off; future `use` directives could override the name. // Since shadowing is forbidden, the only way outstanding_references > 1 in a legal program // is if the name is imported by exactly two `use` directives, one of which resolves to a // value and the other of which resolves to a type. pub outstanding_references: usize, - pub type_ns: ImportResolution, - pub value_ns: ImportResolution, + pub type_ns: ImportResolution<'a>, + pub value_ns: ImportResolution<'a>, } /// Records what we know about an imported name in a namespace (see `ImportResolutionPerNamespace`). #[derive(Clone,Debug)] -pub struct ImportResolution { +pub struct ImportResolution<'a> { /// Whether the name in the namespace was imported with a `use` or a `pub use`. pub is_public: bool, /// Resolution of the name in the namespace - pub target: Option, + pub target: Option>, /// The source node of the `use` directive pub id: NodeId, } -impl ::std::ops::Index for ImportResolutionPerNamespace { - type Output = ImportResolution; - fn index(&self, ns: Namespace) -> &ImportResolution { +impl<'a> ::std::ops::Index for ImportResolutionPerNamespace<'a> { + type Output = ImportResolution<'a>; + fn index(&self, ns: Namespace) -> &ImportResolution<'a> { match ns { TypeNS => &self.type_ns, ValueNS => &self.value_ns } } } -impl ::std::ops::IndexMut for ImportResolutionPerNamespace { - fn index_mut(&mut self, ns: Namespace) -> &mut ImportResolution { +impl<'a> ::std::ops::IndexMut for ImportResolutionPerNamespace<'a> { + fn index_mut(&mut self, ns: Namespace) -> &mut ImportResolution<'a> { match ns { TypeNS => &mut self.type_ns, ValueNS => &mut self.value_ns } } } -impl ImportResolutionPerNamespace { +impl<'a> ImportResolutionPerNamespace<'a> { pub fn new(id: NodeId, is_public: bool) -> Self { let resolution = ImportResolution { id: id, is_public: is_public, target: None }; ImportResolutionPerNamespace { @@ -191,8 +188,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { i, self.resolver.unresolved_imports); - let module_root = self.resolver.graph_root.clone(); - let errors = self.resolve_imports_for_module_subtree(module_root.clone()); + let module_root = self.resolver.graph_root; + let errors = self.resolve_imports_for_module_subtree(module_root); if self.resolver.unresolved_imports == 0 { debug!("(resolving imports) success"); @@ -225,13 +222,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { /// Attempts to resolve imports for the given module and all of its /// submodules. fn resolve_imports_for_module_subtree(&mut self, - module_: Rc) + module_: Module<'b>) -> Vec { let mut errors = Vec::new(); debug!("(resolving imports for module subtree) resolving {}", module_to_string(&*module_)); - let orig_module = replace(&mut self.resolver.current_module, module_.clone()); - errors.extend(self.resolve_imports_for_module(module_.clone())); + let orig_module = replace(&mut self.resolver.current_module, module_); + errors.extend(self.resolve_imports_for_module(module_)); self.resolver.current_module = orig_module; build_reduced_graph::populate_module_if_necessary(self.resolver, &module_); @@ -247,14 +244,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } for (_, child_module) in module_.anonymous_children.borrow().iter() { - errors.extend(self.resolve_imports_for_module_subtree(child_module.clone())); + errors.extend(self.resolve_imports_for_module_subtree(child_module)); } errors } /// Attempts to resolve imports for the given module only. - fn resolve_imports_for_module(&mut self, module: Rc) -> Vec { + fn resolve_imports_for_module(&mut self, module: Module<'b>) -> Vec { let mut errors = Vec::new(); if module.all_imports_resolved() { @@ -268,7 +265,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let mut indeterminate_imports = Vec::new(); while module.resolved_import_count.get() + indeterminate_imports.len() < import_count { let import_index = module.resolved_import_count.get(); - match self.resolve_import_for_module(module.clone(), &imports[import_index]) { + match self.resolve_import_for_module(module, &imports[import_index]) { ResolveResult::Failed(err) => { let import_directive = &imports[import_index]; let (span, help) = match err { @@ -306,7 +303,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { /// currently-unresolved imports, or success if we know the name exists. /// If successful, the resolved bindings are written into the module. fn resolve_import_for_module(&mut self, - module_: Rc, + module_: Module<'b>, import_directive: &ImportDirective) -> ResolveResult<()> { let mut resolution_result = ResolveResult::Failed(None); @@ -319,9 +316,9 @@ 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.clone(), LastMod(AllPublic))) + Some((self.resolver.graph_root, LastMod(AllPublic))) } else { - match self.resolver.resolve_module_path(module_.clone(), + match self.resolver.resolve_module_path(module_, &module_path[..], UseLexicalScopeFlag::DontUseLexicalScope, import_directive.span, @@ -399,8 +396,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } fn resolve_single_import(&mut self, - module_: &Module, - target_module: Rc, + module_: Module<'b>, + target_module: Module<'b>, target: Name, source: Name, directive: &ImportDirective, @@ -447,7 +444,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let mut pub_err = false; if child_name_bindings.value_ns.defined() { debug!("(resolving single import) found value binding"); - value_result = BoundResult(target_module.clone(), + value_result = BoundResult(target_module, 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); @@ -473,7 +470,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } if child_name_bindings.type_ns.defined() { debug!("(resolving single import) found type binding"); - type_result = BoundResult(target_module.clone(), + type_result = BoundResult(target_module, child_name_bindings.type_ns.clone()); if !pub_err && directive.is_public && !child_name_bindings.type_ns.is_public() { @@ -543,11 +540,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } Some(import_resolution) if import_resolution.outstanding_references == 0 => { - fn get_binding(this: &mut Resolver, - import_resolution: &ImportResolutionPerNamespace, - namespace: Namespace, - source: Name) - -> NamespaceResult { + fn get_binding<'a>(this: &mut Resolver, + import_resolution: &ImportResolutionPerNamespace<'a>, + namespace: Namespace, + source: Name) + -> NamespaceResult<'a> { // Import resolutions must be declared with "pub" // in order to be exported. @@ -640,7 +637,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { match type_result { BoundResult(..) => {} _ => { - match target_module.external_module_children.borrow_mut().get(&source).cloned() { + match target_module.external_module_children.borrow_mut().get(&source) { None => {} // Continue. Some(module) => { debug!("(resolving single import) found external module"); @@ -652,7 +649,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { _ => {} } let name_binding = NameBinding::create_from_module(module); - type_result = BoundResult(target_module.clone(), name_binding); + type_result = BoundResult(target_module, name_binding); type_used_public = true; } } @@ -685,7 +682,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { target); import_resolution[namespace] = ImportResolution { - target: Some(Target::new(target_module.clone(), + target: Some(Target::new(target_module, name_binding.clone(), directive.shadowable)), id: directive.id, @@ -777,8 +774,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // that exports nothing is valid). target_module is the module we are // actually importing, i.e., `foo` in `use foo::*`. fn resolve_glob_import(&mut self, - module_: &Module, - target_module: Rc, + module_: Module<'b>, + target_module: Module<'b>, import_directive: &ImportDirective, lp: LastPrivate) -> ResolveResult<()> { @@ -841,7 +838,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { for (&name, name_bindings) in target_module.children.borrow().iter() { self.merge_import_resolution(module_, - target_module.clone(), + target_module, import_directive, name, name_bindings.clone()); @@ -863,11 +860,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } fn merge_import_resolution(&mut self, - module_: &Module, - containing_module: Rc, + module_: Module<'b>, + containing_module: Module<'b>, import_directive: &ImportDirective, name: Name, - name_bindings: NameBindings) { + name_bindings: NameBindings<'b>) { let id = import_directive.id; let is_public = import_directive.is_public; @@ -916,7 +913,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { msg); } else { dest_import_resolution[namespace] = ImportResolution { - target: Some(Target::new(containing_module.clone(), + target: Some(Target::new(containing_module, name_bindings[namespace].clone(), import_directive.shadowable)), id: id, @@ -993,8 +990,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { /// Checks that imported names and items don't have the same name. fn check_for_conflicts_between_imports_and_items(&mut self, - module: &Module, - import: &ImportResolutionPerNamespace, + module: Module<'b>, + import: &ImportResolutionPerNamespace<'b>, import_span: Span, name: Name) { // First, check for conflicts between imports and `extern crate`s. @@ -1013,8 +1010,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } // Check for item conflicts. - let children = module.children.borrow(); - let name_bindings = match children.get(&name) { + let name_bindings = match module.children.borrow().get(&name) { None => { // There can't be any conflicts. return;