Register and stability check #[no_link]
crates.
This commit is contained in:
parent
a1d45d94b0
commit
dd0781ea25
@ -65,6 +65,8 @@ 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.
|
||||
MacrosOnly,
|
||||
/// 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.
|
||||
Implicit,
|
||||
|
@ -124,6 +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 }
|
||||
let src = sess.cstore.used_crate_source(cnum);
|
||||
if src.rlib.is_some() { continue }
|
||||
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
|
||||
// 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 }
|
||||
let name = sess.cstore.crate_name(cnum);
|
||||
let src = sess.cstore.used_crate_source(cnum);
|
||||
if src.dylib.is_some() {
|
||||
|
@ -29,6 +29,7 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(linked_from)]
|
||||
#![feature(concat_idents)]
|
||||
#![cfg_attr(not(stage0), feature(rustc_private))]
|
||||
|
||||
extern crate libc;
|
||||
#[macro_use]
|
||||
|
@ -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)]
|
||||
struct ExternCrateInfo {
|
||||
ident: String,
|
||||
name: String,
|
||||
id: ast::NodeId,
|
||||
should_link: bool,
|
||||
dep_kind: DepKind,
|
||||
}
|
||||
|
||||
fn register_native_lib(sess: &Session,
|
||||
@ -168,7 +164,11 @@ impl<'a> CrateLoader<'a> {
|
||||
ident: i.ident.to_string(),
|
||||
name: name,
|
||||
id: i.id,
|
||||
should_link: should_link(i),
|
||||
dep_kind: if attr::contains_name(&i.attrs, "no_link") {
|
||||
DepKind::MacrosOnly
|
||||
} else {
|
||||
DepKind::Explicit
|
||||
},
|
||||
})
|
||||
}
|
||||
_ => None
|
||||
@ -283,7 +283,7 @@ impl<'a> CrateLoader<'a> {
|
||||
|
||||
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() {
|
||||
self.sess.span_err(span, "crates of the `proc-macro` crate type \
|
||||
@ -427,7 +427,8 @@ impl<'a> CrateLoader<'a> {
|
||||
crate_root: &CrateRoot,
|
||||
metadata: &MetadataBlob,
|
||||
krate: CrateNum,
|
||||
span: Span)
|
||||
span: Span,
|
||||
dep_kind: DepKind)
|
||||
-> cstore::CrateNumMap {
|
||||
debug!("resolving deps of external 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 map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| {
|
||||
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
|
||||
let (local_cnum, ..) = self.resolve_crate(root,
|
||||
&dep.name.as_str(),
|
||||
&dep.name.as_str(),
|
||||
Some(&dep.hash),
|
||||
span,
|
||||
PathKind::Dependency,
|
||||
dep.kind);
|
||||
let dep_name = &dep.name.as_str();
|
||||
let dep_kind = match dep_kind {
|
||||
DepKind::MacrosOnly => DepKind::MacrosOnly,
|
||||
_ => dep.kind,
|
||||
};
|
||||
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();
|
||||
|
||||
@ -455,8 +457,8 @@ impl<'a> CrateLoader<'a> {
|
||||
}
|
||||
|
||||
fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
|
||||
info!("read extension crate {} `extern crate {} as {}` linked={}",
|
||||
info.id, info.name, info.ident, info.should_link);
|
||||
info!("read extension crate {} `extern crate {} as {}` dep_kind={:?}",
|
||||
info.id, info.name, info.ident, info.dep_kind);
|
||||
let target_triple = &self.sess.opts.target_triple[..];
|
||||
let is_cross = target_triple != config::host_triple();
|
||||
let mut target_only = false;
|
||||
@ -641,7 +643,7 @@ impl<'a> CrateLoader<'a> {
|
||||
name: name.to_string(),
|
||||
ident: name.to_string(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
should_link: false,
|
||||
dep_kind: DepKind::MacrosOnly,
|
||||
});
|
||||
|
||||
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 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,
|
||||
// so we return here to avoid registering the crate.
|
||||
if loaded_macros.is_proc_macros() || !info.should_link {
|
||||
// If this is a proc-macro crate, return here to avoid registering.
|
||||
if loaded_macros.is_proc_macros() {
|
||||
return Some(loaded_macros);
|
||||
}
|
||||
|
||||
// Register crate now to avoid double-reading metadata
|
||||
if let PMDSource::Owned(lib) = ekrate.metadata {
|
||||
if ekrate.target_only || config::host_triple() == self.sess.opts.target_triple {
|
||||
let ExternCrateInfo { ref ident, ref name, .. } = info;
|
||||
self.register_crate(&None, ident, name, item.span, lib, DepKind::Explicit);
|
||||
let ExternCrateInfo { ref ident, ref name, dep_kind, .. } = info;
|
||||
self.register_crate(&None, ident, name, item.span, lib, dep_kind);
|
||||
}
|
||||
}
|
||||
|
||||
Some(loaded_macros)
|
||||
} else {
|
||||
if !info.should_link {
|
||||
return None;
|
||||
}
|
||||
None
|
||||
};
|
||||
|
||||
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();
|
||||
|
@ -192,12 +192,13 @@ impl CStore {
|
||||
let mut libs = self.metas
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|(&cnum, data)| {
|
||||
(cnum,
|
||||
match prefer {
|
||||
LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
|
||||
LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
|
||||
})
|
||||
.filter_map(|(&cnum, data)| {
|
||||
if data.dep_kind.get() == DepKind::MacrosOnly { 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),
|
||||
};
|
||||
Some((cnum, path))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
libs.sort_by(|&(a, _), &(b, _)| {
|
||||
|
@ -21,7 +21,7 @@ use rustc::util::nodemap::FxHashMap;
|
||||
use rustc::hir;
|
||||
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_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
|
||||
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)
|
||||
where F: FnMut(def::Export)
|
||||
{
|
||||
if self.dep_kind.get() == DepKind::MacrosOnly {
|
||||
return
|
||||
}
|
||||
|
||||
// Find the item.
|
||||
let item = match self.maybe_entry(id) {
|
||||
None => return,
|
||||
|
@ -22,7 +22,7 @@ use {NameBinding, NameBindingKind, ToNameBinding};
|
||||
use Resolver;
|
||||
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_id::{CrateNum, CRATE_DEF_INDEX, DefId};
|
||||
use rustc::ty;
|
||||
@ -499,8 +499,9 @@ 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 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 {
|
||||
populated: Cell::new(false),
|
||||
..ModuleS::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name()))
|
||||
|
@ -1083,7 +1083,7 @@ pub struct Resolver<'a> {
|
||||
// There will be an anonymous module created around `g` with the ID of the
|
||||
// entry block for `f`.
|
||||
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
|
||||
// when getting additional info for error message suggestions,
|
||||
|
@ -8,11 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:empty-struct.rs
|
||||
|
||||
#[no_link]
|
||||
extern crate libc;
|
||||
extern crate empty_struct;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
libc::abs(0); //~ ERROR unresolved name
|
||||
}
|
||||
empty_struct::XEmpty1; //~ ERROR unresolved name
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user