Skip to content

Commit 39c267a

Browse files
authored
Auto merge of rust-lang#38024 - jseyfried:avoid_needless_proc_macro_deps, r=nrc
Avoid loading needless proc-macro dependencies Fixes rust-lang#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 rust-lang/cargo#3334 for exported proc macros. r? @alexcrichton
2 parents 0b399e5 + 1fd9041 commit 39c267a

File tree

8 files changed

+48
-27
lines changed

8 files changed

+48
-27
lines changed

src/librustc/middle/cstore.rs

+14
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ pub struct CrateSource {
6767

6868
#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
6969
pub enum DepKind {
70+
/// A dependency that is only used for its macros, none of which are visible from other crates.
71+
/// These are included in the metadata only as placeholders and are ignored when decoding.
72+
UnexportedMacrosOnly,
7073
/// A dependency that is only used for its macros.
7174
MacrosOnly,
7275
/// A dependency that is always injected into the dependency list and so
@@ -77,6 +80,15 @@ pub enum DepKind {
7780
Explicit,
7881
}
7982

83+
impl DepKind {
84+
pub fn macros_only(self) -> bool {
85+
match self {
86+
DepKind::UnexportedMacrosOnly | DepKind::MacrosOnly => true,
87+
DepKind::Implicit | DepKind::Explicit => false,
88+
}
89+
}
90+
}
91+
8092
#[derive(PartialEq, Clone, Debug)]
8193
pub enum LibSource {
8294
Some(PathBuf),
@@ -220,6 +232,7 @@ pub trait CrateStore<'tcx> {
220232
fn dylib_dependency_formats(&self, cnum: CrateNum)
221233
-> Vec<(CrateNum, LinkagePreference)>;
222234
fn dep_kind(&self, cnum: CrateNum) -> DepKind;
235+
fn export_macros(&self, cnum: CrateNum);
223236
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
224237
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
225238
fn is_staged_api(&self, cnum: CrateNum) -> bool;
@@ -393,6 +406,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
393406
{ bug!("missing_lang_items") }
394407
fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") }
395408
fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
409+
fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") }
396410
fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
397411
fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
398412
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }

src/librustc/middle/dependency_format.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ fn calculate_type(sess: &session::Session,
124124
return v;
125125
}
126126
for cnum in sess.cstore.crates() {
127-
if sess.cstore.dep_kind(cnum) == DepKind::MacrosOnly { continue }
127+
if sess.cstore.dep_kind(cnum).macros_only() { continue }
128128
let src = sess.cstore.used_crate_source(cnum);
129129
if src.rlib.is_some() { continue }
130130
sess.err(&format!("dependency `{}` not found in rlib format",
@@ -157,7 +157,7 @@ fn calculate_type(sess: &session::Session,
157157
// dependencies, ensuring there are no conflicts. The only valid case for a
158158
// dependency to be relied upon twice is for both cases to rely on a dylib.
159159
for cnum in sess.cstore.crates() {
160-
if sess.cstore.dep_kind(cnum) == DepKind::MacrosOnly { continue }
160+
if sess.cstore.dep_kind(cnum).macros_only() { continue }
161161
let name = sess.cstore.crate_name(cnum);
162162
let src = sess.cstore.used_crate_source(cnum);
163163
if src.dylib.is_some() {

src/librustc_metadata/creader.rs

+13-18
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ impl<'a> CrateLoader<'a> {
171171
name: name,
172172
id: i.id,
173173
dep_kind: if attr::contains_name(&i.attrs, "no_link") {
174-
DepKind::MacrosOnly
174+
DepKind::UnexportedMacrosOnly
175175
} else {
176176
DepKind::Explicit
177177
},
@@ -350,7 +350,7 @@ impl<'a> CrateLoader<'a> {
350350
};
351351

352352
self.load(&mut locate_ctxt).or_else(|| {
353-
dep_kind = DepKind::MacrosOnly;
353+
dep_kind = DepKind::UnexportedMacrosOnly;
354354

355355
let mut proc_macro_locator = locator::Context {
356356
target: &self.sess.host,
@@ -373,7 +373,7 @@ impl<'a> CrateLoader<'a> {
373373
LoadResult::Previous(cnum) => {
374374
let data = self.cstore.get_crate_data(cnum);
375375
if data.root.macro_derive_registrar.is_some() {
376-
dep_kind = DepKind::MacrosOnly;
376+
dep_kind = DepKind::UnexportedMacrosOnly;
377377
}
378378
data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
379379
(cnum, data)
@@ -460,28 +460,23 @@ impl<'a> CrateLoader<'a> {
460460
return cstore::CrateNumMap::new();
461461
}
462462

463-
// The map from crate numbers in the crate we're resolving to local crate
464-
// numbers
465-
let deps = crate_root.crate_deps.decode(metadata);
466-
let map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| {
463+
// The map from crate numbers in the crate we're resolving to local crate numbers.
464+
// We map 0 and all other holes in the map to our parent crate. The "additional"
465+
// self-dependencies should be harmless.
466+
::std::iter::once(krate).chain(crate_root.crate_deps.decode(metadata).map(|dep| {
467467
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
468+
if dep.kind == DepKind::UnexportedMacrosOnly {
469+
return krate;
470+
}
468471
let dep_kind = match dep_kind {
469472
DepKind::MacrosOnly => DepKind::MacrosOnly,
470473
_ => dep.kind,
471474
};
472475
let (local_cnum, ..) = self.resolve_crate(
473476
root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
474477
);
475-
(CrateNum::new(crate_num + 1), local_cnum)
476-
}).collect();
477-
478-
let max_cnum = map.values().cloned().max().map(|cnum| cnum.as_u32()).unwrap_or(0);
479-
480-
// we map 0 and all other holes in the map to our parent crate. The "additional"
481-
// self-dependencies should be harmless.
482-
(0..max_cnum+1).map(|cnum| {
483-
map.get(&CrateNum::from_u32(cnum)).cloned().unwrap_or(krate)
484-
}).collect()
478+
local_cnum
479+
})).collect()
485480
}
486481

487482
fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
@@ -614,7 +609,7 @@ impl<'a> CrateLoader<'a> {
614609
name: Symbol::intern(name),
615610
ident: Symbol::intern(name),
616611
id: ast::DUMMY_NODE_ID,
617-
dep_kind: DepKind::MacrosOnly,
612+
dep_kind: DepKind::UnexportedMacrosOnly,
618613
});
619614

620615
if ekrate.target_only {

src/librustc_metadata/cstore.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ impl CStore {
197197
.borrow()
198198
.iter()
199199
.filter_map(|(&cnum, data)| {
200-
if data.dep_kind.get() == DepKind::MacrosOnly { return None; }
200+
if data.dep_kind.get().macros_only() { return None; }
201201
let path = match prefer {
202202
LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
203203
LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),

src/librustc_metadata/cstore_impl.rs

+6
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
228228
self.get_crate_data(cnum).dep_kind.get()
229229
}
230230

231+
fn export_macros(&self, cnum: CrateNum) {
232+
if self.get_crate_data(cnum).dep_kind.get() == DepKind::UnexportedMacrosOnly {
233+
self.get_crate_data(cnum).dep_kind.set(DepKind::MacrosOnly)
234+
}
235+
}
236+
231237
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>
232238
{
233239
self.get_crate_data(cnum).get_lang_items()

src/librustc_metadata/decoder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc::util::nodemap::FxHashMap;
2121
use rustc::hir;
2222
use rustc::hir::intravisit::IdRange;
2323

24-
use rustc::middle::cstore::{DepKind, InlinedItem, LinkagePreference};
24+
use rustc::middle::cstore::{InlinedItem, LinkagePreference};
2525
use rustc::hir::def::{self, Def, CtorKind};
2626
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
2727
use rustc::middle::lang_items;
@@ -729,7 +729,7 @@ impl<'a, 'tcx> CrateMetadata {
729729
};
730730

731731
// Iterate over all children.
732-
let macros_only = self.dep_kind.get() == DepKind::MacrosOnly;
732+
let macros_only = self.dep_kind.get().macros_only();
733733
for child_index in item.children.decode(self) {
734734
if macros_only {
735735
continue

src/librustc_resolve/build_reduced_graph.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use Namespace::{self, TypeNS, ValueNS, MacroNS};
2121
use ResolveResult::Success;
2222
use {resolve_error, resolve_struct_error, ResolutionError};
2323

24-
use rustc::middle::cstore::{DepKind, LoadedMacro};
24+
use rustc::middle::cstore::LoadedMacro;
2525
use rustc::hir::def::*;
2626
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
2727
use rustc::ty;
@@ -492,7 +492,7 @@ impl<'b> Resolver<'b> {
492492

493493
fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> {
494494
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
495-
let macros_only = self.session.cstore.dep_kind(cnum) == DepKind::MacrosOnly;
495+
let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
496496
let arenas = self.arenas;
497497
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
498498
arenas.alloc_module(ModuleS {
@@ -567,7 +567,8 @@ impl<'b> Resolver<'b> {
567567
if self.current_module.parent.is_some() && legacy_imports != LegacyMacroImports::default() {
568568
span_err!(self.session, item.span, E0468,
569569
"an `extern crate` loading macros must be at the crate root");
570-
} else if self.session.cstore.dep_kind(cnum) == DepKind::MacrosOnly &&
570+
} else if !self.use_extern_macros &&
571+
self.session.cstore.dep_kind(cnum).macros_only() &&
571572
legacy_imports == LegacyMacroImports::default() {
572573
let msg = "custom derive crates and `#[no_link]` crates have no effect without \
573574
`#[macro_use]`";
@@ -590,7 +591,9 @@ impl<'b> Resolver<'b> {
590591
}
591592
}
592593
for (name, span) in legacy_imports.reexports {
593-
self.used_crates.insert(module.def_id().unwrap().krate);
594+
let krate = module.def_id().unwrap().krate;
595+
self.used_crates.insert(krate);
596+
self.session.cstore.export_macros(krate);
594597
let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
595598
if let Success(binding) = result {
596599
self.macro_exports.push(Export { name: name, def: binding.def() });

src/librustc_resolve/resolve_imports.rs

+3
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
743743
(binding.is_import() || binding.is_extern_crate()) {
744744
let def = binding.def();
745745
if def != Def::Err {
746+
if !def.def_id().is_local() {
747+
self.session.cstore.export_macros(def.def_id().krate);
748+
}
746749
reexports.push(Export { name: name, def: def });
747750
}
748751
}

0 commit comments

Comments
 (0)