From 1fd9041b82aaf747f6357686f8d1b3ec83da1f60 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 27 Nov 2016 02:57:15 +0000 Subject: [PATCH] Avoid loading needless proc-macro dependencies. --- src/librustc/middle/cstore.rs | 14 ++++++++++ src/librustc/middle/dependency_format.rs | 4 +-- src/librustc_metadata/creader.rs | 31 +++++++++------------ src/librustc_metadata/cstore.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 6 ++++ src/librustc_metadata/decoder.rs | 4 +-- src/librustc_resolve/build_reduced_graph.rs | 11 +++++--- src/librustc_resolve/resolve_imports.rs | 3 ++ 8 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index a7f28dd6d58..0867e75b9ca 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -67,6 +67,9 @@ pub struct CrateSource { #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] pub enum DepKind { + /// A dependency that is only used for its macros, none of which are visible from other crates. + /// These are included in the metadata only as placeholders and are ignored when decoding. + UnexportedMacrosOnly, /// A dependency that is only used for its macros. MacrosOnly, /// A dependency that is always injected into the dependency list and so @@ -77,6 +80,15 @@ pub enum DepKind { Explicit, } +impl DepKind { + pub fn macros_only(self) -> bool { + match self { + DepKind::UnexportedMacrosOnly | DepKind::MacrosOnly => true, + DepKind::Implicit | DepKind::Explicit => false, + } + } +} + #[derive(PartialEq, Clone, Debug)] pub enum LibSource { Some(PathBuf), @@ -220,6 +232,7 @@ pub trait CrateStore<'tcx> { fn dylib_dependency_formats(&self, cnum: CrateNum) -> Vec<(CrateNum, LinkagePreference)>; fn dep_kind(&self, cnum: CrateNum) -> DepKind; + fn export_macros(&self, cnum: CrateNum); fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>; fn missing_lang_items(&self, cnum: CrateNum) -> Vec; fn is_staged_api(&self, cnum: CrateNum) -> bool; @@ -393,6 +406,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { { bug!("missing_lang_items") } fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") } fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") } + fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") } fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") } fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") } fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") } diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index ee7f13f9e6e..075b3d7a8e9 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -124,7 +124,7 @@ fn calculate_type(sess: &session::Session, return v; } for cnum in sess.cstore.crates() { - if sess.cstore.dep_kind(cnum) == DepKind::MacrosOnly { continue } + if sess.cstore.dep_kind(cnum).macros_only() { continue } let src = sess.cstore.used_crate_source(cnum); if src.rlib.is_some() { continue } sess.err(&format!("dependency `{}` not found in rlib format", @@ -157,7 +157,7 @@ fn calculate_type(sess: &session::Session, // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. for cnum in sess.cstore.crates() { - if sess.cstore.dep_kind(cnum) == DepKind::MacrosOnly { continue } + if sess.cstore.dep_kind(cnum).macros_only() { continue } let name = sess.cstore.crate_name(cnum); let src = sess.cstore.used_crate_source(cnum); if src.dylib.is_some() { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 372152d2b0a..2c266068fe8 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -171,7 +171,7 @@ impl<'a> CrateLoader<'a> { name: name, id: i.id, dep_kind: if attr::contains_name(&i.attrs, "no_link") { - DepKind::MacrosOnly + DepKind::UnexportedMacrosOnly } else { DepKind::Explicit }, @@ -350,7 +350,7 @@ impl<'a> CrateLoader<'a> { }; self.load(&mut locate_ctxt).or_else(|| { - dep_kind = DepKind::MacrosOnly; + dep_kind = DepKind::UnexportedMacrosOnly; let mut proc_macro_locator = locator::Context { target: &self.sess.host, @@ -373,7 +373,7 @@ impl<'a> CrateLoader<'a> { LoadResult::Previous(cnum) => { let data = self.cstore.get_crate_data(cnum); if data.root.macro_derive_registrar.is_some() { - dep_kind = DepKind::MacrosOnly; + dep_kind = DepKind::UnexportedMacrosOnly; } data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind)); (cnum, data) @@ -460,11 +460,14 @@ impl<'a> CrateLoader<'a> { return cstore::CrateNumMap::new(); } - // The map from crate numbers in the crate we're resolving to local crate - // numbers - let deps = crate_root.crate_deps.decode(metadata); - let map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| { + // The map from crate numbers in the crate we're resolving to local crate numbers. + // We map 0 and all other holes in the map to our parent crate. The "additional" + // self-dependencies should be harmless. + ::std::iter::once(krate).chain(crate_root.crate_deps.decode(metadata).map(|dep| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); + if dep.kind == DepKind::UnexportedMacrosOnly { + return krate; + } let dep_kind = match dep_kind { DepKind::MacrosOnly => DepKind::MacrosOnly, _ => dep.kind, @@ -472,16 +475,8 @@ impl<'a> CrateLoader<'a> { let (local_cnum, ..) = self.resolve_crate( root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind, ); - (CrateNum::new(crate_num + 1), local_cnum) - }).collect(); - - let max_cnum = map.values().cloned().max().map(|cnum| cnum.as_u32()).unwrap_or(0); - - // we map 0 and all other holes in the map to our parent crate. The "additional" - // self-dependencies should be harmless. - (0..max_cnum+1).map(|cnum| { - map.get(&CrateNum::from_u32(cnum)).cloned().unwrap_or(krate) - }).collect() + local_cnum + })).collect() } fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate { @@ -614,7 +609,7 @@ impl<'a> CrateLoader<'a> { name: Symbol::intern(name), ident: Symbol::intern(name), id: ast::DUMMY_NODE_ID, - dep_kind: DepKind::MacrosOnly, + dep_kind: DepKind::UnexportedMacrosOnly, }); if ekrate.target_only { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 7c1834c1576..73e03a45196 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -197,7 +197,7 @@ impl CStore { .borrow() .iter() .filter_map(|(&cnum, data)| { - if data.dep_kind.get() == DepKind::MacrosOnly { return None; } + if data.dep_kind.get().macros_only() { return None; } let path = match prefer { LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0), LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0), diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index ead933384b9..4b90d925972 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -228,6 +228,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(cnum).dep_kind.get() } + fn export_macros(&self, cnum: CrateNum) { + if self.get_crate_data(cnum).dep_kind.get() == DepKind::UnexportedMacrosOnly { + self.get_crate_data(cnum).dep_kind.set(DepKind::MacrosOnly) + } + } + fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { self.get_crate_data(cnum).get_lang_items() diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f59f2bcc074..d5b08927a06 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -21,7 +21,7 @@ use rustc::util::nodemap::FxHashMap; use rustc::hir; use rustc::hir::intravisit::IdRange; -use rustc::middle::cstore::{DepKind, InlinedItem, LinkagePreference}; +use rustc::middle::cstore::{InlinedItem, LinkagePreference}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::middle::lang_items; @@ -729,7 +729,7 @@ impl<'a, 'tcx> CrateMetadata { }; // Iterate over all children. - let macros_only = self.dep_kind.get() == DepKind::MacrosOnly; + let macros_only = self.dep_kind.get().macros_only(); for child_index in item.children.decode(self) { if macros_only { continue diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index ff2f25a12fc..854c5f910c1 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -21,7 +21,7 @@ use Namespace::{self, TypeNS, ValueNS, MacroNS}; use ResolveResult::Success; use {resolve_error, resolve_struct_error, ResolutionError}; -use rustc::middle::cstore::{DepKind, LoadedMacro}; +use rustc::middle::cstore::LoadedMacro; use rustc::hir::def::*; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::ty; @@ -492,7 +492,7 @@ impl<'b> Resolver<'b> { fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> { let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; - let macros_only = self.session.cstore.dep_kind(cnum) == DepKind::MacrosOnly; + let macros_only = self.session.cstore.dep_kind(cnum).macros_only(); let arenas = self.arenas; *self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| { arenas.alloc_module(ModuleS { @@ -567,7 +567,8 @@ impl<'b> Resolver<'b> { if self.current_module.parent.is_some() && legacy_imports != LegacyMacroImports::default() { span_err!(self.session, item.span, E0468, "an `extern crate` loading macros must be at the crate root"); - } else if self.session.cstore.dep_kind(cnum) == DepKind::MacrosOnly && + } else if !self.use_extern_macros && + self.session.cstore.dep_kind(cnum).macros_only() && legacy_imports == LegacyMacroImports::default() { let msg = "custom derive crates and `#[no_link]` crates have no effect without \ `#[macro_use]`"; @@ -590,7 +591,9 @@ impl<'b> Resolver<'b> { } } for (name, span) in legacy_imports.reexports { - self.used_crates.insert(module.def_id().unwrap().krate); + let krate = module.def_id().unwrap().krate; + self.used_crates.insert(krate); + self.session.cstore.export_macros(krate); let result = self.resolve_name_in_module(module, name, MacroNS, false, None); if let Success(binding) = result { self.macro_exports.push(Export { name: name, def: binding.def() }); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 47bd1f71084..5c9e8bb9371 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -743,6 +743,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { (binding.is_import() || binding.is_extern_crate()) { let def = binding.def(); if def != Def::Err { + if !def.def_id().is_local() { + self.session.cstore.export_macros(def.def_id().krate); + } reexports.push(Export { name: name, def: def }); } }