Skip to content

Commit dd0781e

Browse files
committed
Register and stability check #[no_link] crates.
1 parent a1d45d9 commit dd0781e

File tree

9 files changed

+50
-41
lines changed

9 files changed

+50
-41
lines changed

src/librustc/middle/cstore.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ pub struct CrateSource {
6565

6666
#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
6767
pub enum DepKind {
68+
/// A dependency that is only used for its macros.
69+
MacrosOnly,
6870
/// A dependency that is always injected into the dependency list and so
6971
/// doesn't need to be linked to an rlib, e.g. the injected allocator.
7072
Implicit,

src/librustc/middle/dependency_format.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +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 }
127128
let src = sess.cstore.used_crate_source(cnum);
128129
if src.rlib.is_some() { continue }
129130
sess.err(&format!("dependency `{}` not found in rlib format",
@@ -156,6 +157,7 @@ fn calculate_type(sess: &session::Session,
156157
// dependencies, ensuring there are no conflicts. The only valid case for a
157158
// dependency to be relied upon twice is for both cases to rely on a dylib.
158159
for cnum in sess.cstore.crates() {
160+
if sess.cstore.dep_kind(cnum) == DepKind::MacrosOnly { continue }
159161
let name = sess.cstore.crate_name(cnum);
160162
let src = sess.cstore.used_crate_source(cnum);
161163
if src.dylib.is_some() {

src/librustc_llvm/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#![feature(staged_api)]
3030
#![feature(linked_from)]
3131
#![feature(concat_idents)]
32+
#![cfg_attr(not(stage0), feature(rustc_private))]
3233

3334
extern crate libc;
3435
#[macro_use]

src/librustc_metadata/creader.rs

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,12 @@ fn dump_crates(cstore: &CStore) {
6767
})
6868
}
6969

70-
fn should_link(i: &ast::Item) -> bool {
71-
!attr::contains_name(&i.attrs, "no_link")
72-
}
73-
7470
#[derive(Debug)]
7571
struct ExternCrateInfo {
7672
ident: String,
7773
name: String,
7874
id: ast::NodeId,
79-
should_link: bool,
75+
dep_kind: DepKind,
8076
}
8177

8278
fn register_native_lib(sess: &Session,
@@ -168,7 +164,11 @@ impl<'a> CrateLoader<'a> {
168164
ident: i.ident.to_string(),
169165
name: name,
170166
id: i.id,
171-
should_link: should_link(i),
167+
dep_kind: if attr::contains_name(&i.attrs, "no_link") {
168+
DepKind::MacrosOnly
169+
} else {
170+
DepKind::Explicit
171+
},
172172
})
173173
}
174174
_ => None
@@ -283,7 +283,7 @@ impl<'a> CrateLoader<'a> {
283283

284284
let Library { dylib, rlib, metadata } = lib;
285285

286-
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span);
286+
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
287287

288288
if crate_root.macro_derive_registrar.is_some() {
289289
self.sess.span_err(span, "crates of the `proc-macro` crate type \
@@ -427,21 +427,23 @@ impl<'a> CrateLoader<'a> {
427427
crate_root: &CrateRoot,
428428
metadata: &MetadataBlob,
429429
krate: CrateNum,
430-
span: Span)
430+
span: Span,
431+
dep_kind: DepKind)
431432
-> cstore::CrateNumMap {
432433
debug!("resolving deps of external crate");
433434
// The map from crate numbers in the crate we're resolving to local crate
434435
// numbers
435436
let deps = crate_root.crate_deps.decode(metadata);
436437
let map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| {
437438
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
438-
let (local_cnum, ..) = self.resolve_crate(root,
439-
&dep.name.as_str(),
440-
&dep.name.as_str(),
441-
Some(&dep.hash),
442-
span,
443-
PathKind::Dependency,
444-
dep.kind);
439+
let dep_name = &dep.name.as_str();
440+
let dep_kind = match dep_kind {
441+
DepKind::MacrosOnly => DepKind::MacrosOnly,
442+
_ => dep.kind,
443+
};
444+
let (local_cnum, ..) = self.resolve_crate(
445+
root, dep_name, dep_name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
446+
);
445447
(CrateNum::new(crate_num + 1), local_cnum)
446448
}).collect();
447449

@@ -455,8 +457,8 @@ impl<'a> CrateLoader<'a> {
455457
}
456458

457459
fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
458-
info!("read extension crate {} `extern crate {} as {}` linked={}",
459-
info.id, info.name, info.ident, info.should_link);
460+
info!("read extension crate {} `extern crate {} as {}` dep_kind={:?}",
461+
info.id, info.name, info.ident, info.dep_kind);
460462
let target_triple = &self.sess.opts.target_triple[..];
461463
let is_cross = target_triple != config::host_triple();
462464
let mut target_only = false;
@@ -641,7 +643,7 @@ impl<'a> CrateLoader<'a> {
641643
name: name.to_string(),
642644
ident: name.to_string(),
643645
id: ast::DUMMY_NODE_ID,
644-
should_link: false,
646+
dep_kind: DepKind::MacrosOnly,
645647
});
646648

647649
if ekrate.target_only {
@@ -984,30 +986,26 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
984986
let ekrate = self.read_extension_crate(item.span, &info);
985987
let loaded_macros = self.read_macros(item, &ekrate);
986988

987-
// If this is a proc-macro crate or `#[no_link]` crate, it is only used at compile time,
988-
// so we return here to avoid registering the crate.
989-
if loaded_macros.is_proc_macros() || !info.should_link {
989+
// If this is a proc-macro crate, return here to avoid registering.
990+
if loaded_macros.is_proc_macros() {
990991
return Some(loaded_macros);
991992
}
992993

993994
// Register crate now to avoid double-reading metadata
994995
if let PMDSource::Owned(lib) = ekrate.metadata {
995996
if ekrate.target_only || config::host_triple() == self.sess.opts.target_triple {
996-
let ExternCrateInfo { ref ident, ref name, .. } = info;
997-
self.register_crate(&None, ident, name, item.span, lib, DepKind::Explicit);
997+
let ExternCrateInfo { ref ident, ref name, dep_kind, .. } = info;
998+
self.register_crate(&None, ident, name, item.span, lib, dep_kind);
998999
}
9991000
}
10001001

10011002
Some(loaded_macros)
10021003
} else {
1003-
if !info.should_link {
1004-
return None;
1005-
}
10061004
None
10071005
};
10081006

10091007
let (cnum, ..) = self.resolve_crate(
1010-
&None, &info.ident, &info.name, None, item.span, PathKind::Crate, DepKind::Explicit,
1008+
&None, &info.ident, &info.name, None, item.span, PathKind::Crate, info.dep_kind,
10111009
);
10121010

10131011
let def_id = definitions.opt_local_def_id(item.id).unwrap();

src/librustc_metadata/cstore.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,13 @@ impl CStore {
192192
let mut libs = self.metas
193193
.borrow()
194194
.iter()
195-
.map(|(&cnum, data)| {
196-
(cnum,
197-
match prefer {
198-
LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
199-
LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
200-
})
195+
.filter_map(|(&cnum, data)| {
196+
if data.dep_kind.get() == DepKind::MacrosOnly { return None; }
197+
let path = match prefer {
198+
LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
199+
LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
200+
};
201+
Some((cnum, path))
201202
})
202203
.collect::<Vec<_>>();
203204
libs.sort_by(|&(a, _), &(b, _)| {

src/librustc_metadata/decoder.rs

Lines changed: 5 additions & 1 deletion
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::{InlinedItem, LinkagePreference};
24+
use rustc::middle::cstore::{DepKind, InlinedItem, LinkagePreference};
2525
use rustc::hir::def::{self, Def, CtorKind};
2626
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
2727
use rustc::middle::lang_items;
@@ -690,6 +690,10 @@ impl<'a, 'tcx> CrateMetadata {
690690
pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
691691
where F: FnMut(def::Export)
692692
{
693+
if self.dep_kind.get() == DepKind::MacrosOnly {
694+
return
695+
}
696+
693697
// Find the item.
694698
let item = match self.maybe_entry(id) {
695699
None => return,

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use {NameBinding, NameBindingKind, ToNameBinding};
2222
use Resolver;
2323
use {resolve_error, resolve_struct_error, ResolutionError};
2424

25-
use rustc::middle::cstore::LoadedMacros;
25+
use rustc::middle::cstore::{DepKind, LoadedMacros};
2626
use rustc::hir::def::*;
2727
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
2828
use rustc::ty;
@@ -499,8 +499,9 @@ impl<'b> Resolver<'b> {
499499

500500
fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> {
501501
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
502+
let macros_only = self.session.cstore.dep_kind(cnum) == DepKind::MacrosOnly;
502503
let arenas = self.arenas;
503-
*self.extern_crate_roots.entry(cnum).or_insert_with(|| {
504+
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
504505
arenas.alloc_module(ModuleS {
505506
populated: Cell::new(false),
506507
..ModuleS::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name()))

src/librustc_resolve/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ pub struct Resolver<'a> {
10831083
// There will be an anonymous module created around `g` with the ID of the
10841084
// entry block for `f`.
10851085
module_map: NodeMap<Module<'a>>,
1086-
extern_crate_roots: FxHashMap<CrateNum, Module<'a>>,
1086+
extern_crate_roots: FxHashMap<(CrateNum, bool /* MacrosOnly? */), Module<'a>>,
10871087

10881088
// Whether or not to print error messages. Can be set to true
10891089
// when getting additional info for error message suggestions,

src/test/compile-fail/no-link.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// aux-build:empty-struct.rs
12+
1113
#[no_link]
12-
extern crate libc;
14+
extern crate empty_struct;
1315

1416
fn main() {
15-
unsafe {
16-
libc::abs(0); //~ ERROR unresolved name
17-
}
17+
empty_struct::XEmpty1; //~ ERROR unresolved name
1818
}

0 commit comments

Comments
 (0)