about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/cstore.rs2
-rw-r--r--src/librustc/middle/dependency_format.rs2
-rw-r--r--src/librustc_llvm/lib.rs1
-rw-r--r--src/librustc_metadata/creader.rs52
-rw-r--r--src/librustc_metadata/cstore.rs13
-rw-r--r--src/librustc_metadata/decoder.rs6
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs5
-rw-r--r--src/librustc_resolve/lib.rs2
-rw-r--r--src/test/compile-fail/no-link.rs8
9 files changed, 50 insertions, 41 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index cb2a4b3f622..bdef44bf5c1 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -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,
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 2267c42b543..92d1ab85c5a 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -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() {
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index da09bfa66d2..07b87072c43 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -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]
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 08168fd4fd7..9101f95c882 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -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();
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 36d55dd95b9..10e86c427a8 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -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, _)| {
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 7973cd880fe..1da26418965 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -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,
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index d987930544e..ed87c61ef3b 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -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()))
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b16b61b46b8..89a0826254c 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -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,
diff --git a/src/test/compile-fail/no-link.rs b/src/test/compile-fail/no-link.rs
index 8f6da99806b..5ea07403cf7 100644
--- a/src/test/compile-fail/no-link.rs
+++ b/src/test/compile-fail/no-link.rs
@@ -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
 }