diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d18e5d4ab08..e1708be30d9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -63,9 +63,9 @@ use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField}; use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics}; -use syntax::ast::{Ident, ImplItem, Item, ItemEnum, ItemFn, ItemForeignMod}; -use syntax::ast::{ItemImpl, ItemMac, ItemMod, ItemStatic, ItemStruct}; -use syntax::ast::{ItemTrait, ItemTy, LOCAL_CRATE, Local, ItemConst}; +use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn}; +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use syntax::ast::{ItemStruct, ItemTrait, ItemTy, Local}; use syntax::ast::{MethodImplItem, Mod, Name, NamedField, NodeId}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; use syntax::ast::{PatRange, PatStruct, Path, PathListIdent, PathListMod}; @@ -97,6 +97,7 @@ use std::rc::{Rc, Weak}; use std::uint; mod check_unused; +mod record_exports; #[deriving(Copy)] struct BindingInfo { @@ -3708,124 +3709,6 @@ impl<'a> Resolver<'a> { } } - // Export recording - // - // This pass simply determines what all "export" keywords refer to and - // writes the results into the export map. - // - // FIXME #4953 This pass will be removed once exports change to per-item. - // Then this operation can simply be performed as part of item (or import) - // processing. - - fn record_exports(&mut self) { - let root_module = self.graph_root.get_module(); - self.record_exports_for_module_subtree(root_module); - } - - fn record_exports_for_module_subtree(&mut self, - module_: Rc) { - // If this isn't a local krate, then bail out. We don't need to record - // exports for nonlocal crates. - - match module_.def_id.get() { - Some(def_id) if def_id.krate == LOCAL_CRATE => { - // OK. Continue. - debug!("(recording exports for module subtree) recording \ - exports for local module `{}`", - self.module_to_string(&*module_)); - } - None => { - // Record exports for the root module. - debug!("(recording exports for module subtree) recording \ - exports for root module `{}`", - self.module_to_string(&*module_)); - } - Some(_) => { - // Bail out. - debug!("(recording exports for module subtree) not recording \ - exports for `{}`", - self.module_to_string(&*module_)); - return; - } - } - - self.record_exports_for_module(&*module_); - self.populate_module_if_necessary(&module_); - - for (_, child_name_bindings) in module_.children.borrow().iter() { - match child_name_bindings.get_module_if_available() { - None => { - // Nothing to do. - } - Some(child_module) => { - self.record_exports_for_module_subtree(child_module); - } - } - } - - for (_, child_module) in module_.anonymous_children.borrow().iter() { - self.record_exports_for_module_subtree(child_module.clone()); - } - } - - fn record_exports_for_module(&mut self, module_: &Module) { - let mut exports = Vec::new(); - - self.add_exports_for_module(&mut exports, module_); - match module_.def_id.get() { - Some(def_id) => { - self.export_map.insert(def_id.node, exports); - debug!("(computing exports) writing exports for {} (some)", - def_id.node); - } - None => {} - } - } - - fn add_exports_of_namebindings(&mut self, - exports: &mut Vec, - name: Name, - namebindings: &NameBindings, - ns: Namespace) { - match namebindings.def_for_namespace(ns) { - Some(d) => { - debug!("(computing exports) YES: export '{}' => {}", - name, d.def_id()); - exports.push(Export { - name: name, - def_id: d.def_id() - }); - } - d_opt => { - debug!("(computing exports) NO: {}", d_opt); - } - } - } - - fn add_exports_for_module(&mut self, - exports: &mut Vec, - module_: &Module) { - for (name, importresolution) in module_.import_resolutions.borrow().iter() { - if !importresolution.is_public { - continue - } - let xs = [TypeNS, ValueNS]; - for &ns in xs.iter() { - match importresolution.target_for_namespace(ns) { - Some(target) => { - debug!("(computing exports) maybe export '{}'", - token::get_name(*name)); - self.add_exports_of_namebindings(exports, - *name, - &*target.bindings, - ns) - } - _ => () - } - } - } - } - // AST resolution // // We maintain a list of value ribs and type ribs. @@ -6137,7 +6020,7 @@ pub fn resolve_crate(session: &Session, resolver.resolve_imports(); session.abort_if_errors(); - resolver.record_exports(); + record_exports::record(&mut resolver); session.abort_if_errors(); resolver.resolve_crate(krate); diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs new file mode 100644 index 00000000000..41882a94b34 --- /dev/null +++ b/src/librustc_resolve/record_exports.rs @@ -0,0 +1,157 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// Export recording +// +// This pass simply determines what all "export" keywords refer to and +// writes the results into the export map. +// +// FIXME #4953 This pass will be removed once exports change to per-item. +// Then this operation can simply be performed as part of item (or import) +// processing. + +use {Module, NameBindings, Resolver}; +use Namespace::{mod, TypeNS, ValueNS}; + +use rustc::middle::def::Export; +use syntax::ast; +use syntax::parse::token; + +use std::rc::Rc; + +struct ExportRecorder<'a, 'b:'a> { + resolver: &'a mut Resolver<'b> +} + +// Deref and DerefMut impls allow treating ExportRecorder as Resolver. +impl<'a, 'b> Deref> for ExportRecorder<'a, 'b> { + fn deref<'c>(&'c self) -> &'c Resolver<'b> { + &*self.resolver + } +} + +impl<'a, 'b> DerefMut> for ExportRecorder<'a, 'b> { + fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> { + &mut *self.resolver + } +} + +impl<'a, 'b> ExportRecorder<'a, 'b> { + fn record_exports_for_module_subtree(&mut self, + module_: Rc) { + // If this isn't a local krate, then bail out. We don't need to record + // exports for nonlocal crates. + + match module_.def_id.get() { + Some(def_id) if def_id.krate == ast::LOCAL_CRATE => { + // OK. Continue. + debug!("(recording exports for module subtree) recording \ + exports for local module `{}`", + self.module_to_string(&*module_)); + } + None => { + // Record exports for the root module. + debug!("(recording exports for module subtree) recording \ + exports for root module `{}`", + self.module_to_string(&*module_)); + } + Some(_) => { + // Bail out. + debug!("(recording exports for module subtree) not recording \ + exports for `{}`", + self.module_to_string(&*module_)); + return; + } + } + + self.record_exports_for_module(&*module_); + self.populate_module_if_necessary(&module_); + + for (_, child_name_bindings) in module_.children.borrow().iter() { + match child_name_bindings.get_module_if_available() { + None => { + // Nothing to do. + } + Some(child_module) => { + self.record_exports_for_module_subtree(child_module); + } + } + } + + for (_, child_module) in module_.anonymous_children.borrow().iter() { + self.record_exports_for_module_subtree(child_module.clone()); + } + } + + fn record_exports_for_module(&mut self, module_: &Module) { + let mut exports = Vec::new(); + + self.add_exports_for_module(&mut exports, module_); + match module_.def_id.get() { + Some(def_id) => { + self.export_map.insert(def_id.node, exports); + debug!("(computing exports) writing exports for {} (some)", + def_id.node); + } + None => {} + } + } + + fn add_exports_of_namebindings(&mut self, + exports: &mut Vec, + name: ast::Name, + namebindings: &NameBindings, + ns: Namespace) { + match namebindings.def_for_namespace(ns) { + Some(d) => { + debug!("(computing exports) YES: export '{}' => {}", + name, d.def_id()); + exports.push(Export { + name: name, + def_id: d.def_id() + }); + } + d_opt => { + debug!("(computing exports) NO: {}", d_opt); + } + } + } + + fn add_exports_for_module(&mut self, + exports: &mut Vec, + module_: &Module) { + for (name, importresolution) in module_.import_resolutions.borrow().iter() { + if !importresolution.is_public { + continue + } + let xs = [TypeNS, ValueNS]; + for &ns in xs.iter() { + match importresolution.target_for_namespace(ns) { + Some(target) => { + debug!("(computing exports) maybe export '{}'", + token::get_name(*name)); + self.add_exports_of_namebindings(exports, + *name, + &*target.bindings, + ns) + } + _ => () + } + } + } + } +} + +pub fn record(resolver: &mut Resolver) { + let mut recorder = ExportRecorder { resolver: resolver }; + let root_module = recorder.graph_root.get_module(); + recorder.record_exports_for_module_subtree(root_module); +}