mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Auto merge of #38024 - jseyfried:avoid_needless_proc_macro_deps, r=nrc
Avoid loading needless proc-macro dependencies Fixes #37958 when no proc-macros are exported; in particular, without `pub extern crate proc_macros;`, `#![feature(macro_reexport)]`, or `#![feature(use_extern_macros)]`. I opened https://github.com/rust-lang/cargo/issues/3334 for exported proc macros. r? @alexcrichton
This commit is contained in:
commit
39c267a8d5
@ -67,6 +67,9 @@ pub struct CrateSource {
|
|||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
|
#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
|
||||||
pub enum DepKind {
|
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.
|
/// A dependency that is only used for its macros.
|
||||||
MacrosOnly,
|
MacrosOnly,
|
||||||
/// A dependency that is always injected into the dependency list and so
|
/// A dependency that is always injected into the dependency list and so
|
||||||
@ -77,6 +80,15 @@ pub enum DepKind {
|
|||||||
Explicit,
|
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)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub enum LibSource {
|
pub enum LibSource {
|
||||||
Some(PathBuf),
|
Some(PathBuf),
|
||||||
@ -220,6 +232,7 @@ pub trait CrateStore<'tcx> {
|
|||||||
fn dylib_dependency_formats(&self, cnum: CrateNum)
|
fn dylib_dependency_formats(&self, cnum: CrateNum)
|
||||||
-> Vec<(CrateNum, LinkagePreference)>;
|
-> Vec<(CrateNum, LinkagePreference)>;
|
||||||
fn dep_kind(&self, cnum: CrateNum) -> DepKind;
|
fn dep_kind(&self, cnum: CrateNum) -> DepKind;
|
||||||
|
fn export_macros(&self, cnum: CrateNum);
|
||||||
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
|
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
|
||||||
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
|
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
|
||||||
fn is_staged_api(&self, cnum: CrateNum) -> bool;
|
fn is_staged_api(&self, cnum: CrateNum) -> bool;
|
||||||
@ -393,6 +406,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||||||
{ bug!("missing_lang_items") }
|
{ bug!("missing_lang_items") }
|
||||||
fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") }
|
fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") }
|
||||||
fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
|
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_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
|
||||||
fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
|
fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
|
||||||
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
|
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
|
||||||
|
@ -124,7 +124,7 @@ fn calculate_type(sess: &session::Session,
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
for cnum in sess.cstore.crates() {
|
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);
|
let src = sess.cstore.used_crate_source(cnum);
|
||||||
if src.rlib.is_some() { continue }
|
if src.rlib.is_some() { continue }
|
||||||
sess.err(&format!("dependency `{}` not found in rlib format",
|
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
|
// 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.
|
// dependency to be relied upon twice is for both cases to rely on a dylib.
|
||||||
for cnum in sess.cstore.crates() {
|
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 name = sess.cstore.crate_name(cnum);
|
||||||
let src = sess.cstore.used_crate_source(cnum);
|
let src = sess.cstore.used_crate_source(cnum);
|
||||||
if src.dylib.is_some() {
|
if src.dylib.is_some() {
|
||||||
|
@ -171,7 +171,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
name: name,
|
name: name,
|
||||||
id: i.id,
|
id: i.id,
|
||||||
dep_kind: if attr::contains_name(&i.attrs, "no_link") {
|
dep_kind: if attr::contains_name(&i.attrs, "no_link") {
|
||||||
DepKind::MacrosOnly
|
DepKind::UnexportedMacrosOnly
|
||||||
} else {
|
} else {
|
||||||
DepKind::Explicit
|
DepKind::Explicit
|
||||||
},
|
},
|
||||||
@ -350,7 +350,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.load(&mut locate_ctxt).or_else(|| {
|
self.load(&mut locate_ctxt).or_else(|| {
|
||||||
dep_kind = DepKind::MacrosOnly;
|
dep_kind = DepKind::UnexportedMacrosOnly;
|
||||||
|
|
||||||
let mut proc_macro_locator = locator::Context {
|
let mut proc_macro_locator = locator::Context {
|
||||||
target: &self.sess.host,
|
target: &self.sess.host,
|
||||||
@ -373,7 +373,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
LoadResult::Previous(cnum) => {
|
LoadResult::Previous(cnum) => {
|
||||||
let data = self.cstore.get_crate_data(cnum);
|
let data = self.cstore.get_crate_data(cnum);
|
||||||
if data.root.macro_derive_registrar.is_some() {
|
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));
|
data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
|
||||||
(cnum, data)
|
(cnum, data)
|
||||||
@ -460,11 +460,14 @@ impl<'a> CrateLoader<'a> {
|
|||||||
return cstore::CrateNumMap::new();
|
return cstore::CrateNumMap::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The map from crate numbers in the crate we're resolving to local crate
|
// The map from crate numbers in the crate we're resolving to local crate numbers.
|
||||||
// numbers
|
// We map 0 and all other holes in the map to our parent crate. The "additional"
|
||||||
let deps = crate_root.crate_deps.decode(metadata);
|
// self-dependencies should be harmless.
|
||||||
let map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| {
|
::std::iter::once(krate).chain(crate_root.crate_deps.decode(metadata).map(|dep| {
|
||||||
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
|
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
|
||||||
|
if dep.kind == DepKind::UnexportedMacrosOnly {
|
||||||
|
return krate;
|
||||||
|
}
|
||||||
let dep_kind = match dep_kind {
|
let dep_kind = match dep_kind {
|
||||||
DepKind::MacrosOnly => DepKind::MacrosOnly,
|
DepKind::MacrosOnly => DepKind::MacrosOnly,
|
||||||
_ => dep.kind,
|
_ => dep.kind,
|
||||||
@ -472,16 +475,8 @@ impl<'a> CrateLoader<'a> {
|
|||||||
let (local_cnum, ..) = self.resolve_crate(
|
let (local_cnum, ..) = self.resolve_crate(
|
||||||
root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
|
root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
|
||||||
);
|
);
|
||||||
(CrateNum::new(crate_num + 1), local_cnum)
|
local_cnum
|
||||||
}).collect();
|
})).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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
|
fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
|
||||||
@ -614,7 +609,7 @@ impl<'a> CrateLoader<'a> {
|
|||||||
name: Symbol::intern(name),
|
name: Symbol::intern(name),
|
||||||
ident: Symbol::intern(name),
|
ident: Symbol::intern(name),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
dep_kind: DepKind::MacrosOnly,
|
dep_kind: DepKind::UnexportedMacrosOnly,
|
||||||
});
|
});
|
||||||
|
|
||||||
if ekrate.target_only {
|
if ekrate.target_only {
|
||||||
|
@ -197,7 +197,7 @@ impl CStore {
|
|||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(&cnum, data)| {
|
.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 {
|
let path = match prefer {
|
||||||
LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
|
LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
|
||||||
LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
|
LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
|
||||||
|
@ -228,6 +228,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
|||||||
self.get_crate_data(cnum).dep_kind.get()
|
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)>
|
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>
|
||||||
{
|
{
|
||||||
self.get_crate_data(cnum).get_lang_items()
|
self.get_crate_data(cnum).get_lang_items()
|
||||||
|
@ -21,7 +21,7 @@ use rustc::util::nodemap::FxHashMap;
|
|||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::intravisit::IdRange;
|
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::{self, Def, CtorKind};
|
||||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
@ -729,7 +729,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Iterate over all children.
|
// 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) {
|
for child_index in item.children.decode(self) {
|
||||||
if macros_only {
|
if macros_only {
|
||||||
continue
|
continue
|
||||||
|
@ -21,7 +21,7 @@ use Namespace::{self, TypeNS, ValueNS, MacroNS};
|
|||||||
use ResolveResult::Success;
|
use ResolveResult::Success;
|
||||||
use {resolve_error, resolve_struct_error, ResolutionError};
|
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::*;
|
||||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
|
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
@ -492,7 +492,7 @@ impl<'b> Resolver<'b> {
|
|||||||
|
|
||||||
fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> {
|
fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> {
|
||||||
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
|
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;
|
let arenas = self.arenas;
|
||||||
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
|
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
|
||||||
arenas.alloc_module(ModuleS {
|
arenas.alloc_module(ModuleS {
|
||||||
@ -567,7 +567,8 @@ impl<'b> Resolver<'b> {
|
|||||||
if self.current_module.parent.is_some() && legacy_imports != LegacyMacroImports::default() {
|
if self.current_module.parent.is_some() && legacy_imports != LegacyMacroImports::default() {
|
||||||
span_err!(self.session, item.span, E0468,
|
span_err!(self.session, item.span, E0468,
|
||||||
"an `extern crate` loading macros must be at the crate root");
|
"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() {
|
legacy_imports == LegacyMacroImports::default() {
|
||||||
let msg = "custom derive crates and `#[no_link]` crates have no effect without \
|
let msg = "custom derive crates and `#[no_link]` crates have no effect without \
|
||||||
`#[macro_use]`";
|
`#[macro_use]`";
|
||||||
@ -590,7 +591,9 @@ impl<'b> Resolver<'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (name, span) in legacy_imports.reexports {
|
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);
|
let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
|
||||||
if let Success(binding) = result {
|
if let Success(binding) = result {
|
||||||
self.macro_exports.push(Export { name: name, def: binding.def() });
|
self.macro_exports.push(Export { name: name, def: binding.def() });
|
||||||
|
@ -743,6 +743,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||||||
(binding.is_import() || binding.is_extern_crate()) {
|
(binding.is_import() || binding.is_extern_crate()) {
|
||||||
let def = binding.def();
|
let def = binding.def();
|
||||||
if def != Def::Err {
|
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 });
|
reexports.push(Export { name: name, def: def });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user