Register and stability check #[no_link] crates.

This commit is contained in:
Jeffrey Seyfried 2016-10-28 05:56:06 +00:00
parent a1d45d94b0
commit dd0781ea25
9 changed files with 50 additions and 41 deletions

View File

@ -65,6 +65,8 @@ 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.
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
/// doesn't need to be linked to an rlib, e.g. the injected allocator. /// doesn't need to be linked to an rlib, e.g. the injected allocator.
Implicit, Implicit,

View File

@ -124,6 +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 }
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",
@ -156,6 +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 }
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() {

View File

@ -29,6 +29,7 @@
#![feature(staged_api)] #![feature(staged_api)]
#![feature(linked_from)] #![feature(linked_from)]
#![feature(concat_idents)] #![feature(concat_idents)]
#![cfg_attr(not(stage0), feature(rustc_private))]
extern crate libc; extern crate libc;
#[macro_use] #[macro_use]

View File

@ -67,16 +67,12 @@ fn dump_crates(cstore: &CStore) {
}) })
} }
fn should_link(i: &ast::Item) -> bool {
!attr::contains_name(&i.attrs, "no_link")
}
#[derive(Debug)] #[derive(Debug)]
struct ExternCrateInfo { struct ExternCrateInfo {
ident: String, ident: String,
name: String, name: String,
id: ast::NodeId, id: ast::NodeId,
should_link: bool, dep_kind: DepKind,
} }
fn register_native_lib(sess: &Session, fn register_native_lib(sess: &Session,
@ -168,7 +164,11 @@ impl<'a> CrateLoader<'a> {
ident: i.ident.to_string(), ident: i.ident.to_string(),
name: name, name: name,
id: i.id, id: i.id,
should_link: should_link(i), dep_kind: if attr::contains_name(&i.attrs, "no_link") {
DepKind::MacrosOnly
} else {
DepKind::Explicit
},
}) })
} }
_ => None _ => None
@ -283,7 +283,7 @@ impl<'a> CrateLoader<'a> {
let Library { dylib, rlib, metadata } = lib; let Library { dylib, rlib, metadata } = lib;
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span); let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
if crate_root.macro_derive_registrar.is_some() { if crate_root.macro_derive_registrar.is_some() {
self.sess.span_err(span, "crates of the `proc-macro` crate type \ self.sess.span_err(span, "crates of the `proc-macro` crate type \
@ -427,7 +427,8 @@ impl<'a> CrateLoader<'a> {
crate_root: &CrateRoot, crate_root: &CrateRoot,
metadata: &MetadataBlob, metadata: &MetadataBlob,
krate: CrateNum, krate: CrateNum,
span: Span) span: Span,
dep_kind: DepKind)
-> cstore::CrateNumMap { -> cstore::CrateNumMap {
debug!("resolving deps of external crate"); debug!("resolving deps of external crate");
// 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
@ -435,13 +436,14 @@ impl<'a> CrateLoader<'a> {
let deps = crate_root.crate_deps.decode(metadata); let deps = crate_root.crate_deps.decode(metadata);
let map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| { let map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| {
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
let (local_cnum, ..) = self.resolve_crate(root, let dep_name = &dep.name.as_str();
&dep.name.as_str(), let dep_kind = match dep_kind {
&dep.name.as_str(), DepKind::MacrosOnly => DepKind::MacrosOnly,
Some(&dep.hash), _ => dep.kind,
span, };
PathKind::Dependency, let (local_cnum, ..) = self.resolve_crate(
dep.kind); root, dep_name, dep_name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
);
(CrateNum::new(crate_num + 1), local_cnum) (CrateNum::new(crate_num + 1), local_cnum)
}).collect(); }).collect();
@ -455,8 +457,8 @@ impl<'a> CrateLoader<'a> {
} }
fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate { fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
info!("read extension crate {} `extern crate {} as {}` linked={}", info!("read extension crate {} `extern crate {} as {}` dep_kind={:?}",
info.id, info.name, info.ident, info.should_link); info.id, info.name, info.ident, info.dep_kind);
let target_triple = &self.sess.opts.target_triple[..]; let target_triple = &self.sess.opts.target_triple[..];
let is_cross = target_triple != config::host_triple(); let is_cross = target_triple != config::host_triple();
let mut target_only = false; let mut target_only = false;
@ -641,7 +643,7 @@ impl<'a> CrateLoader<'a> {
name: name.to_string(), name: name.to_string(),
ident: name.to_string(), ident: name.to_string(),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
should_link: false, dep_kind: DepKind::MacrosOnly,
}); });
if ekrate.target_only { if ekrate.target_only {
@ -984,30 +986,26 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
let ekrate = self.read_extension_crate(item.span, &info); let ekrate = self.read_extension_crate(item.span, &info);
let loaded_macros = self.read_macros(item, &ekrate); let loaded_macros = self.read_macros(item, &ekrate);
// If this is a proc-macro crate or `#[no_link]` crate, it is only used at compile time, // If this is a proc-macro crate, return here to avoid registering.
// so we return here to avoid registering the crate. if loaded_macros.is_proc_macros() {
if loaded_macros.is_proc_macros() || !info.should_link {
return Some(loaded_macros); return Some(loaded_macros);
} }
// Register crate now to avoid double-reading metadata // Register crate now to avoid double-reading metadata
if let PMDSource::Owned(lib) = ekrate.metadata { if let PMDSource::Owned(lib) = ekrate.metadata {
if ekrate.target_only || config::host_triple() == self.sess.opts.target_triple { if ekrate.target_only || config::host_triple() == self.sess.opts.target_triple {
let ExternCrateInfo { ref ident, ref name, .. } = info; let ExternCrateInfo { ref ident, ref name, dep_kind, .. } = info;
self.register_crate(&None, ident, name, item.span, lib, DepKind::Explicit); self.register_crate(&None, ident, name, item.span, lib, dep_kind);
} }
} }
Some(loaded_macros) Some(loaded_macros)
} else { } else {
if !info.should_link {
return None;
}
None None
}; };
let (cnum, ..) = self.resolve_crate( let (cnum, ..) = self.resolve_crate(
&None, &info.ident, &info.name, None, item.span, PathKind::Crate, DepKind::Explicit, &None, &info.ident, &info.name, None, item.span, PathKind::Crate, info.dep_kind,
); );
let def_id = definitions.opt_local_def_id(item.id).unwrap(); let def_id = definitions.opt_local_def_id(item.id).unwrap();

View File

@ -192,12 +192,13 @@ impl CStore {
let mut libs = self.metas let mut libs = self.metas
.borrow() .borrow()
.iter() .iter()
.map(|(&cnum, data)| { .filter_map(|(&cnum, data)| {
(cnum, if data.dep_kind.get() == DepKind::MacrosOnly { return None; }
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),
}) };
Some((cnum, path))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
libs.sort_by(|&(a, _), &(b, _)| { libs.sort_by(|&(a, _), &(b, _)| {

View File

@ -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::{InlinedItem, LinkagePreference}; use rustc::middle::cstore::{DepKind, InlinedItem, LinkagePreference};
use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use rustc::middle::lang_items; use rustc::middle::lang_items;
@ -690,6 +690,10 @@ impl<'a, 'tcx> CrateMetadata {
pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F) pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
where F: FnMut(def::Export) where F: FnMut(def::Export)
{ {
if self.dep_kind.get() == DepKind::MacrosOnly {
return
}
// Find the item. // Find the item.
let item = match self.maybe_entry(id) { let item = match self.maybe_entry(id) {
None => return, None => return,

View File

@ -22,7 +22,7 @@ use {NameBinding, NameBindingKind, ToNameBinding};
use Resolver; use Resolver;
use {resolve_error, resolve_struct_error, ResolutionError}; use {resolve_error, resolve_struct_error, ResolutionError};
use rustc::middle::cstore::LoadedMacros; use rustc::middle::cstore::{DepKind, LoadedMacros};
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;
@ -499,8 +499,9 @@ 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 arenas = self.arenas; let arenas = self.arenas;
*self.extern_crate_roots.entry(cnum).or_insert_with(|| { *self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
arenas.alloc_module(ModuleS { arenas.alloc_module(ModuleS {
populated: Cell::new(false), populated: Cell::new(false),
..ModuleS::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name())) ..ModuleS::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name()))

View File

@ -1083,7 +1083,7 @@ pub struct Resolver<'a> {
// There will be an anonymous module created around `g` with the ID of the // There will be an anonymous module created around `g` with the ID of the
// entry block for `f`. // entry block for `f`.
module_map: NodeMap<Module<'a>>, module_map: NodeMap<Module<'a>>,
extern_crate_roots: FxHashMap<CrateNum, Module<'a>>, extern_crate_roots: FxHashMap<(CrateNum, bool /* MacrosOnly? */), Module<'a>>,
// Whether or not to print error messages. Can be set to true // Whether or not to print error messages. Can be set to true
// when getting additional info for error message suggestions, // when getting additional info for error message suggestions,

View File

@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// aux-build:empty-struct.rs
#[no_link] #[no_link]
extern crate libc; extern crate empty_struct;
fn main() { fn main() {
unsafe { empty_struct::XEmpty1; //~ ERROR unresolved name
libc::abs(0); //~ ERROR unresolved name
}
} }