resolve: use arena allocation instead of reference counting for `Module`s to fix memory leaks from Rc cycles

This commit is contained in:
Jeffrey Seyfried 2016-01-11 21:19:29 +00:00
parent 69e1f57dfb
commit a8514d3ecc
5 changed files with 260 additions and 245 deletions

View File

@ -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

View File

@ -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<Module>,
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<Module>, 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<Module>) -> Rc<Module> {
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<Module>,
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<Module>) {
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<Module>) -> Rc<Module> {
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<Module>) {
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<Module>,
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<Module>) {
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<Module>) {
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<Module>) {
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<Name>,
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<Module>,
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<Module>) {
pub fn populate_module_if_necessary<'a, 'tcx>(resolver: &mut Resolver<'a, 'tcx>,
module: Module<'a>) {
GraphBuilder { resolver: resolver }.populate_module_if_necessary(module);
}

View File

@ -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<Module>, 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<Module>, 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<Module>, Name),
BlockParentLink(Weak<Module>, 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<Option<Def>>,
is_public: bool,
children: RefCell<HashMap<Name, NameBindings>>,
children: RefCell<HashMap<Name, NameBindings<'a>>>,
imports: RefCell<Vec<ImportDirective>>,
// The external module children of this node that were declared with
// `extern crate`.
external_module_children: RefCell<HashMap<Name, Rc<Module>>>,
external_module_children: RefCell<HashMap<Name, Module<'a>>>,
// 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<NodeMap<Rc<Module>>>,
anonymous_children: RefCell<NodeMap<Module<'a>>>,
// The status of resolving each import in this module.
import_resolutions: RefCell<HashMap<Name, ImportResolutionPerNamespace>>,
import_resolutions: RefCell<HashMap<Name, ImportResolutionPerNamespace<'a>>>,
// The number of unresolved globs that this module exports.
glob_count: Cell<usize>,
@ -886,13 +887,11 @@ pub struct Module {
populated: Cell<bool>,
}
impl Module {
fn new(parent_link: ParentLink,
def: Option<Def>,
external: bool,
is_public: bool)
-> Rc<Module> {
Rc::new(Module {
pub type Module<'a> = &'a ModuleS<'a>;
impl<'a> ModuleS<'a> {
fn new(parent_link: ParentLink<'a>, def: Option<Def>, 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<DefId> {
@ -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<Span>,
}
#[derive(Debug)]
enum DefOrModule {
enum DefOrModule<'a> {
Def(Def),
Module(Rc<Module>),
Module(Module<'a>),
}
impl NsDef {
fn create_from_module(module: Rc<Module>, span: Option<Span>) -> Self {
impl<'a> NsDef<'a> {
fn create_from_module(module: Module<'a>, span: Option<Span>) -> 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<Rc<Module>> {
fn module(&self) -> Option<Module<'a>> {
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<RefCell<Option<NsDef>>>);
pub struct NameBinding<'a>(Rc<RefCell<Option<NsDef<'a>>>>);
impl NameBinding {
impl<'a> NameBinding<'a> {
fn new() -> Self {
NameBinding(Rc::new(RefCell::new(None)))
}
fn create_from_module(module: Rc<Module>) -> 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<Option<NsDef>> {
fn borrow(&self) -> ::std::cell::Ref<Option<NsDef<'a>>> {
self.0.borrow()
}
@ -1062,7 +1059,7 @@ impl NameBinding {
fn def(&self) -> Option<Def> {
self.borrow().as_ref().and_then(NsDef::def)
}
fn module(&self) -> Option<Rc<Module>> {
fn module(&self) -> Option<Module<'a>> {
self.borrow().as_ref().and_then(NsDef::module)
}
fn span(&self) -> Option<Span> {
@ -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<Namespace> for NameBindings {
type Output = NameBinding;
fn index(&self, namespace: Namespace) -> &NameBinding {
impl<'a> ::std::ops::Index<Namespace> 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<Module>, 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<Module>,
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<Module>,
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<ModuleS<'a>>,
}
#[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<Def>,
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_: Module<'a>,
module_path: &[Name],
index: usize,
span: Span,
name_search_type: NameSearchType,
lp: LastPrivate)
-> ResolveResult<(Rc<Module>, LastPrivate)> {
fn search_parent_externals(needle: Name, module: &Rc<Module>) -> Option<Rc<Module>> {
-> ResolveResult<(Module<'a>, LastPrivate)> {
fn search_parent_externals<'a>(needle: Name, module: Module<'a>)
-> Option<Module<'a>> {
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_: Module<'a>,
module_path: &[Name],
use_lexical_scope: UseLexicalScopeFlag,
span: Span,
name_search_type: NameSearchType)
-> ResolveResult<(Rc<Module>, 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_: 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_: Module<'a>,
name: Name)
-> ResolveResult<Rc<Module>> {
-> ResolveResult<Module<'a>> {
// 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<Module>) -> Option<Rc<Module>> {
fn get_nearest_normal_module_parent(&mut self, module_: Module<'a>) -> Option<Module<'a>> {
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<Module>) -> Rc<Module> {
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_: Module<'a>,
module_path: &[Name])
-> ResolveResult<ModulePrefixResult> {
-> ResolveResult<ModulePrefixResult<'a>> {
// 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_: 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<Module>) {
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<F>(&mut self, name: Option<Name>, 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::<Vec<_>>();
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<Def> {
// 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<Rc<Module>> {
let root = this.current_module.clone();
fn get_module<'a, 'tcx>(this: &mut Resolver<'a, 'tcx>,
span: Span,
name_path: &[ast::Name])
-> Option<Module<'a>> {
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::<Vec<_>>();
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<Module>) {
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<ast::Name>, module: &Module) {
fn collect_mod<'a>(names: &mut Vec<ast::Name>, 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<Box<Fn(hir_map::Node, &mut bool) -> 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;

View File

@ -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<Module>) {
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<Export>, module_: &Module) {
fn add_exports_for_module(&mut self, exports: &mut Vec<Export>, 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);
}

View File

@ -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<Module>,
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<Module>,
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<Target>,
pub target: Option<Target<'a>>,
/// The source node of the `use` directive
pub id: NodeId,
}
impl ::std::ops::Index<Namespace> for ImportResolutionPerNamespace {
type Output = ImportResolution;
fn index(&self, ns: Namespace) -> &ImportResolution {
impl<'a> ::std::ops::Index<Namespace> 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<Namespace> for ImportResolutionPerNamespace {
fn index_mut(&mut self, ns: Namespace) -> &mut ImportResolution {
impl<'a> ::std::ops::IndexMut<Namespace> 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_: Module<'b>)
-> Vec<ImportResolvingError> {
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<Module>) -> Vec<ImportResolvingError> {
fn resolve_imports_for_module(&mut self, module: Module<'b>) -> Vec<ImportResolvingError> {
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_: 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_: 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_: 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_: 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;