From 7b5c59ea6506f9addc3cab6d4af062e7df607aac Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 16 Sep 2016 02:52:09 +0000 Subject: [PATCH] Load extern crates in `resolve`. --- src/librustc/dep_graph/dep_node.rs | 2 - src/librustc/middle/cstore.rs | 8 +- src/librustc_driver/driver.rs | 14 +- src/librustc_metadata/creader.rs | 183 ++++++++------------ src/librustc_metadata/macro_import.rs | 33 +--- src/librustc_resolve/build_reduced_graph.rs | 2 + src/librustc_resolve/lib.rs | 9 +- src/librustc_resolve/macros.rs | 2 +- 8 files changed, 98 insertions(+), 155 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 269f0ebb813..e99ffa95ed6 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -51,7 +51,6 @@ pub enum DepNode { WorkProduct(Arc), // Represents different phases in the compiler. - CrateReader, CollectLanguageItems, CheckStaticRecursion, ResolveLifetimes, @@ -171,7 +170,6 @@ impl DepNode { match *self { Krate => Some(Krate), - CrateReader => Some(CrateReader), CollectLanguageItems => Some(CollectLanguageItems), CheckStaticRecursion => Some(CheckStaticRecursion), ResolveLifetimes => Some(ResolveLifetimes), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index e57e116cea7..62e0de1ba67 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -25,7 +25,7 @@ use hir::def::{self, Def}; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; -use hir::map::definitions::DefKey; +use hir::map::definitions::{Definitions, DefKey}; use hir::svh::Svh; use middle::lang_items; use ty::{self, Ty, TyCtxt}; @@ -422,6 +422,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } } -pub trait MacroLoader { - fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec; +pub trait CrateLoader { + fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec; + fn process_item(&mut self, item: &ast::Item, defs: &Definitions); + fn postprocess(&mut self, krate: &ast::Crate); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 18ce35237af..ae80bc53c4c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -28,8 +28,7 @@ use rustc_back::sha2::{Sha256, Digest}; use rustc_borrowck as borrowck; use rustc_incremental::{self, IncrementalHashesMap}; use rustc_resolve::{MakeGlobMap, Resolver}; -use rustc_metadata::macro_import; -use rustc_metadata::creader::read_local_crates; +use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::CStore; use rustc_trans::back::{link, write}; use rustc_trans as trans; @@ -639,12 +638,10 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, } sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?; - let mut macro_loader = - macro_import::MacroLoader::new(sess, &cstore, crate_name, krate.config.clone()); - + let mut crate_loader = CrateLoader::new(sess, &cstore, &krate, crate_name); let resolver_arenas = Resolver::arenas(); let mut resolver = - Resolver::new(sess, &krate, make_glob_map, &mut macro_loader, &resolver_arenas); + Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas); syntax_ext::register_builtins(&mut resolver, sess.features.borrow().quote); krate = time(time_passes, "expansion", || { @@ -736,11 +733,6 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, // Collect defintions for def ids. time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate)); - time(sess.time_passes(), "external crate/lib resolution", || { - let defs = &resolver.definitions; - read_local_crates(sess, &cstore, defs, &krate, crate_name, &sess.dep_graph) - }); - time(sess.time_passes(), "early lint checks", || lint::check_ast_crate(sess, &krate)); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 95be77c24f4..71cc13aebb3 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -12,14 +12,15 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use loader::{self, CratePaths}; +use macro_import; use schema::CrateRoot; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; -use rustc::dep_graph::{DepGraph, DepNode}; use rustc::session::{config, Session}; use rustc::session::config::PanicStrategy; use rustc::session::search_paths::PathKind; +use rustc::middle; use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate}; use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use rustc::hir::map as hir_map; @@ -31,20 +32,18 @@ use std::rc::Rc; use std::fs; use syntax::ast; +use syntax::ext::base::LoadedMacro; use syntax::abi::Abi; use syntax::parse; use syntax::attr; use syntax::parse::token::InternedString; -use syntax::visit; use syntax_pos::{self, Span, mk_sp}; use log; -struct LocalCrateReader<'a> { - sess: &'a Session, +pub struct CrateLoader<'a> { + pub sess: &'a Session, + pub creader: CrateReader<'a>, cstore: &'a CStore, - creader: CrateReader<'a>, - krate: &'a ast::Crate, - definitions: &'a hir_map::Definitions, } pub struct CrateReader<'a> { @@ -56,13 +55,6 @@ pub struct CrateReader<'a> { local_crate_config: ast::CrateConfig, } -impl<'a> visit::Visitor for LocalCrateReader<'a> { - fn visit_item(&mut self, a: &ast::Item) { - self.process_item(a); - visit::walk_item(self, a); - } -} - fn dump_crates(cstore: &CStore) { info!("resolved crates:"); cstore.iter_crate_data_origins(|_, data, opt_source| { @@ -918,98 +910,22 @@ impl ExtensionCrate { } } -impl<'a> LocalCrateReader<'a> { - fn new(sess: &'a Session, - cstore: &'a CStore, - defs: &'a hir_map::Definitions, - krate: &'a ast::Crate, - local_crate_name: &str) - -> LocalCrateReader<'a> { - LocalCrateReader { +impl<'a> CrateLoader<'a> { + pub fn new(sess: &'a Session, cstore: &'a CStore, krate: &ast::Crate, crate_name: &str) + -> Self { + let loader = CrateLoader { sess: sess, cstore: cstore, - creader: CrateReader::new(sess, cstore, local_crate_name, krate.config.clone()), - krate: krate, - definitions: defs, - } - } + creader: CrateReader::new(sess, cstore, crate_name, krate.config.clone()), + }; - // Traverses an AST, reading all the information about use'd crates and - // extern libraries necessary for later resolving, typechecking, linking, - // etc. - fn read_crates(&mut self, dep_graph: &DepGraph) { - let _task = dep_graph.in_task(DepNode::CrateReader); - - self.process_crate(self.krate); - visit::walk_crate(self, self.krate); - self.creader.inject_allocator_crate(); - self.creader.inject_panic_runtime(self.krate); - - if log_enabled!(log::INFO) { - dump_crates(&self.cstore); - } - - for &(ref name, kind) in &self.sess.opts.libs { - register_native_lib(self.sess, self.cstore, None, name.clone(), kind); - } - self.creader.register_statically_included_foreign_items(); - } - - fn process_crate(&self, c: &ast::Crate) { - for a in c.attrs.iter().filter(|m| m.name() == "link_args") { - if let Some(ref linkarg) = a.value_str() { - self.cstore.add_used_link_args(&linkarg); + for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") { + if let Some(ref linkarg) = attr.value_str() { + loader.cstore.add_used_link_args(&linkarg); } } - } - fn process_item(&mut self, i: &ast::Item) { - match i.node { - ast::ItemKind::ExternCrate(_) => { - // If this `extern crate` item has `#[macro_use]` then we can - // safely skip it. These annotations were processed during macro - // expansion and are already loaded (if necessary) into our - // crate store. - // - // Note that it's important we *don't* fall through below as - // some `#[macro_use]` crate are explicitly not linked (e.g. - // macro crates) so we want to ensure we avoid `resolve_crate` - // with those. - if attr::contains_name(&i.attrs, "macro_use") { - if self.cstore.was_used_for_derive_macros(i) { - return - } - } - - if let Some(info) = self.creader.extract_crate_info(i) { - if !info.should_link { - return; - } - let (cnum, ..) = self.creader.resolve_crate(&None, - &info.ident, - &info.name, - None, - i.span, - PathKind::Crate, - true); - - let def_id = self.definitions.opt_local_def_id(i.id).unwrap(); - let len = self.definitions.def_path(def_id.index).data.len(); - - self.creader.update_extern_crate(cnum, - ExternCrate { - def_id: def_id, - span: i.span, - direct: true, - path_len: len, - }, - &mut FnvHashSet()); - self.cstore.add_extern_mod_stmt_cnum(info.id, cnum); - } - } - ast::ItemKind::ForeignMod(ref fm) => self.process_foreign_mod(i, fm), - _ => { } - } + loader } fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) { @@ -1073,13 +989,62 @@ impl<'a> LocalCrateReader<'a> { } } -/// Traverses an AST, reading all the information about use'd crates and extern -/// libraries necessary for later resolving, typechecking, linking, etc. -pub fn read_local_crates(sess: & Session, - cstore: & CStore, - defs: & hir_map::Definitions, - krate: & ast::Crate, - local_crate_name: &str, - dep_graph: &DepGraph) { - LocalCrateReader::new(sess, cstore, defs, krate, local_crate_name).read_crates(dep_graph) +impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { + fn postprocess(&mut self, krate: &ast::Crate) { + self.creader.inject_allocator_crate(); + self.creader.inject_panic_runtime(krate); + + if log_enabled!(log::INFO) { + dump_crates(&self.cstore); + } + + for &(ref name, kind) in &self.sess.opts.libs { + register_native_lib(self.sess, self.cstore, None, name.clone(), kind); + } + self.creader.register_statically_included_foreign_items(); + } + + fn process_item(&mut self, item: &ast::Item, definitions: &hir_map::Definitions) { + match item.node { + ast::ItemKind::ExternCrate(_) => {} + ast::ItemKind::ForeignMod(ref fm) => return self.process_foreign_mod(item, fm), + _ => return, + } + + // If this `extern crate` item has `#[macro_use]` then we can safely skip it. + // These annotations were processed during macro expansion and are already loaded + // (if necessary) into our crate store. + // + // Note that it's important we *don't* fall through below as some `#[macro_use]` + // crates are explicitly not linked (e.g. macro crates) so we want to ensure + // we avoid `resolve_crate` with those. + if attr::contains_name(&item.attrs, "macro_use") { + if self.cstore.was_used_for_derive_macros(item) { + return + } + } + + if let Some(info) = self.creader.extract_crate_info(item) { + if !info.should_link { + return; + } + + let (cnum, ..) = self.creader.resolve_crate( + &None, &info.ident, &info.name, None, item.span, PathKind::Crate, true, + ); + + let def_id = definitions.opt_local_def_id(item.id).unwrap(); + let len = definitions.def_path(def_id.index).data.len(); + + let extern_crate = + ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len }; + self.creader.update_extern_crate(cnum, extern_crate, &mut FnvHashSet()); + + self.cstore.add_extern_mod_stmt_cnum(info.id, cnum); + } + } + + fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec { + macro_import::load_macros(self, extern_crate, allows_macros) + } } diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs index e41f076d64a..3fe44045256 100644 --- a/src/librustc_metadata/macro_import.rs +++ b/src/librustc_metadata/macro_import.rs @@ -14,11 +14,9 @@ use std::collections::HashSet; use std::env; use std::mem; -use creader::{CrateReader, Macros}; -use cstore::CStore; +use creader::{CrateLoader, Macros}; use rustc::hir::def_id::DefIndex; -use rustc::middle; use rustc::session::Session; use rustc::util::nodemap::FnvHashMap; use rustc_back::dynamic_lib::DynamicLibrary; @@ -31,31 +29,18 @@ use syntax::parse::token; use syntax_ext::deriving::custom::CustomDerive; use syntax_pos::Span; -pub struct MacroLoader<'a> { - sess: &'a Session, - reader: CrateReader<'a>, -} - -impl<'a> MacroLoader<'a> { - pub fn new(sess: &'a Session, - cstore: &'a CStore, - crate_name: &str, - crate_config: ast::CrateConfig) - -> MacroLoader<'a> { - MacroLoader { - sess: sess, - reader: CrateReader::new(sess, cstore, crate_name, crate_config), - } - } -} - pub fn call_bad_macro_reexport(a: &Session, b: Span) { span_err!(a, b, E0467, "bad macro reexport"); } pub type MacroSelection = FnvHashMap; -impl<'a> middle::cstore::MacroLoader for MacroLoader<'a> { +pub fn load_macros(loader: &mut CrateLoader, extern_crate: &ast::Item, allows_macros: bool) + -> Vec { + loader.load_crate(extern_crate, allows_macros) +} + +impl<'a> CrateLoader<'a> { fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec { @@ -108,9 +93,7 @@ impl<'a> middle::cstore::MacroLoader for MacroLoader<'a> { self.load_macros(extern_crate, allows_macros, import, reexport) } -} -impl<'a> MacroLoader<'a> { fn load_macros<'b>(&mut self, vi: &ast::Item, allows_macros: bool, @@ -129,7 +112,7 @@ impl<'a> MacroLoader<'a> { return Vec::new(); } - let mut macros = self.reader.read_macros(vi); + let mut macros = self.creader.read_macros(vi); let mut ret = Vec::new(); let mut seen = HashSet::new(); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3075e394869..9202f8c0946 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -79,6 +79,8 @@ impl<'b> Resolver<'b> { /// Constructs the reduced graph for one item. fn build_reduced_graph_for_item(&mut self, item: &Item) { + self.crate_loader.process_item(item, &self.definitions); + let parent = self.current_module; let name = item.ident.name; let sp = item.span; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0d75685df55..63ff9de2be2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -44,7 +44,7 @@ use self::ModulePrefixResult::*; use rustc::hir::map::Definitions; use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; -use rustc::middle::cstore::MacroLoader; +use rustc::middle::cstore::CrateLoader; use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; @@ -1066,7 +1066,7 @@ pub struct Resolver<'a> { dummy_binding: &'a NameBinding<'a>, new_import_semantics: bool, // true if `#![feature(item_like_imports)]` - macro_loader: &'a mut MacroLoader, + crate_loader: &'a mut CrateLoader, macro_names: FnvHashSet, // Maps the `Mark` of an expansion to its containing module or block. @@ -1172,7 +1172,7 @@ impl<'a> Resolver<'a> { pub fn new(session: &'a Session, krate: &Crate, make_glob_map: MakeGlobMap, - macro_loader: &'a mut MacroLoader, + crate_loader: &'a mut CrateLoader, arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX)); @@ -1240,7 +1240,7 @@ impl<'a> Resolver<'a> { }), new_import_semantics: session.features.borrow().item_like_imports, - macro_loader: macro_loader, + crate_loader: crate_loader, macro_names: FnvHashSet(), expansion_data: expansion_data, } @@ -1263,6 +1263,7 @@ impl<'a> Resolver<'a> { check_unused::check_crate(self, krate); self.report_errors(); + self.crate_loader.postprocess(krate); } fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index c9aa7d6a330..0b2a70bf4a6 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -38,7 +38,7 @@ struct ModuleData { impl<'a> base::Resolver for Resolver<'a> { fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec { - self.macro_loader.load_crate(extern_crate, allows_macros) + self.crate_loader.load_macros(extern_crate, allows_macros) } fn next_node_id(&mut self) -> ast::NodeId {