about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-12-06 10:54:45 +0000
committerbors <bors@rust-lang.org>2016-12-06 10:54:45 +0000
commit1692c0b587e1d91bb96a99f9f2588d7d2b247e3f (patch)
tree97531974dddac60a84b7e0576382abfe9c07e6c1
parentff261d3a6b5964e1e3744d055238de624afc5d76 (diff)
parent7d05d1e7f0add9e5151d48d51d92b6fb5885e257 (diff)
downloadrust-1692c0b587e1d91bb96a99f9f2588d7d2b247e3f.tar.gz
rust-1692c0b587e1d91bb96a99f9f2588d7d2b247e3f.zip
Auto merge of #37973 - vadimcn:dllimport, r=alexcrichton
Implement RFC 1717

Implement the first two points from #37403.

r? @alexcrichton
-rw-r--r--src/librustc/middle/cstore.rs11
-rw-r--r--src/librustc/session/config.rs72
-rw-r--r--src/librustc_llvm/ffi.rs8
-rw-r--r--src/librustc_llvm/lib.rs2
-rw-r--r--src/librustc_metadata/creader.rs156
-rw-r--r--src/librustc_metadata/cstore.rs21
-rw-r--r--src/librustc_metadata/cstore_impl.rs14
-rw-r--r--src/librustc_metadata/decoder.rs4
-rw-r--r--src/librustc_trans/base.rs3
-rw-r--r--src/librustc_trans/callee.rs6
-rw-r--r--src/librustc_trans/consts.rs13
-rw-r--r--src/libsyntax/feature_gate.rs7
-rw-r--r--src/test/codegen/dllimports/auxiliary/dummy.rs16
-rw-r--r--src/test/codegen/dllimports/auxiliary/wrapper.rs24
-rw-r--r--src/test/codegen/dllimports/main.rs64
-rw-r--r--src/test/compile-fail/rfc1717/missing-link-attr.rs14
-rw-r--r--src/test/compile-fail/rfc1717/multiple-renames.rs17
-rw-r--r--src/test/compile-fail/rfc1717/rename-to-empty.rs17
-rw-r--r--src/test/run-make/c-static-dylib/foo.rs2
-rw-r--r--src/test/run-make/c-static-rlib/foo.rs2
-rw-r--r--src/test/run-make/extern-fn-generic/test.rs2
-rw-r--r--src/test/run-make/extern-fn-generic/testcrate.rs2
-rw-r--r--src/test/run-make/interdependent-c-libraries/bar.rs2
-rw-r--r--src/test/run-make/interdependent-c-libraries/foo.rs2
-rw-r--r--src/test/run-make/issue-15460/foo.rs2
-rw-r--r--src/test/run-make/issue-25581/test.rs2
-rw-r--r--src/test/run-make/link-path-order/main.rs2
-rw-r--r--src/test/run-pass/abi-sysv64-arg-passing.rs2
-rw-r--r--src/test/run-pass/anon-extern-mod.rs2
-rw-r--r--src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs2
-rw-r--r--src/test/run-pass/auxiliary/extern-crosscrate-source.rs2
-rw-r--r--src/test/run-pass/auxiliary/foreign_lib.rs2
-rw-r--r--src/test/run-pass/auxiliary/issue-25185-1.rs3
-rw-r--r--src/test/run-pass/c-stack-as-value.rs2
-rw-r--r--src/test/run-pass/cabi-int-widening.rs2
-rw-r--r--src/test/run-pass/extern-call-deep.rs2
-rw-r--r--src/test/run-pass/extern-call-deep2.rs2
-rw-r--r--src/test/run-pass/extern-call-indirect.rs2
-rw-r--r--src/test/run-pass/extern-call-scrub.rs2
-rw-r--r--src/test/run-pass/extern-pass-TwoU16s.rs2
-rw-r--r--src/test/run-pass/extern-pass-TwoU32s.rs2
-rw-r--r--src/test/run-pass/extern-pass-TwoU64s.rs2
-rw-r--r--src/test/run-pass/extern-pass-TwoU8s.rs2
-rw-r--r--src/test/run-pass/extern-pass-char.rs2
-rw-r--r--src/test/run-pass/extern-pass-double.rs2
-rw-r--r--src/test/run-pass/extern-pass-empty.rs2
-rw-r--r--src/test/run-pass/extern-pass-u32.rs2
-rw-r--r--src/test/run-pass/extern-pass-u64.rs2
-rw-r--r--src/test/run-pass/extern-return-TwoU16s.rs2
-rw-r--r--src/test/run-pass/extern-return-TwoU32s.rs2
-rw-r--r--src/test/run-pass/extern-return-TwoU64s.rs2
-rw-r--r--src/test/run-pass/extern-return-TwoU8s.rs2
-rw-r--r--src/test/run-pass/foreign-call-no-runtime.rs2
-rw-r--r--src/test/run-pass/foreign-fn-with-byval.rs2
-rw-r--r--src/test/run-pass/foreign-no-abi.rs2
-rw-r--r--src/test/run-pass/issue-28676.rs2
-rw-r--r--src/test/run-pass/mir_trans_calls_variadic.rs2
-rw-r--r--src/test/run-pass/rfc1717/auxiliary/clibrary.rs (renamed from src/test/compile-fail/feature-gate-linked-from.rs)11
-rw-r--r--src/test/run-pass/rfc1717/library-override.rs23
-rw-r--r--src/test/run-pass/segfault-no-out-of-stack.rs2
-rw-r--r--src/test/run-pass/static-mut-foreign.rs2
-rw-r--r--src/test/run-pass/struct-return.rs2
-rw-r--r--src/test/run-pass/union/union-c-interop.rs2
-rw-r--r--src/test/run-pass/variadic-ffi.rs2
64 files changed, 437 insertions, 155 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 4357518b332..78bbb03f40d 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -131,6 +131,7 @@ pub struct NativeLibrary {
     pub kind: NativeLibraryKind,
     pub name: Symbol,
     pub cfg: Option<ast::MetaItem>,
+    pub foreign_items: Vec<DefIndex>,
 }
 
 /// The data we save and restore about an inlined item or method.  This is not
@@ -305,7 +306,8 @@ pub trait CrateStore<'tcx> {
     fn is_defaulted_trait(&self, did: DefId) -> bool;
     fn is_default_impl(&self, impl_did: DefId) -> bool;
     fn is_foreign_item(&self, did: DefId) -> bool;
-    fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool;
+    fn is_dllimport_foreign_item(&self, def: DefId) -> bool;
+    fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool;
 
     // crate metadata
     fn dylib_dependency_formats(&self, cnum: CrateNum)
@@ -463,7 +465,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     fn is_defaulted_trait(&self, did: DefId) -> bool { bug!("is_defaulted_trait") }
     fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
     fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") }
-    fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false }
+    fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false }
+    fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false }
 
     // crate metadata
     fn dylib_dependency_formats(&self, cnum: CrateNum)
@@ -529,9 +532,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     // This is basically a 1-based range of ints, which is a little
     // silly - I may fix that.
     fn crates(&self) -> Vec<CrateNum> { vec![] }
-    fn used_libraries(&self) -> Vec<NativeLibrary> {
-        vec![]
-    }
+    fn used_libraries(&self) -> Vec<NativeLibrary> { vec![] }
     fn used_link_args(&self) -> Vec<String> { vec![] }
 
     // utility functions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 130f598d7f4..47f0de3ce57 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -262,7 +262,7 @@ top_level_options!(
         //            much sense: The search path can stay the same while the
         //            things discovered there might have changed on disk.
         search_paths: SearchPaths [TRACKED],
-        libs: Vec<(String, cstore::NativeLibraryKind)> [TRACKED],
+        libs: Vec<(String, Option<String>, cstore::NativeLibraryKind)> [TRACKED],
         maybe_sysroot: Option<PathBuf> [TRACKED],
 
         target_triple: String [TRACKED],
@@ -1449,6 +1449,8 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     }
 
     let libs = matches.opt_strs("l").into_iter().map(|s| {
+        // Parse string of the form "[KIND=]lib[:new_name]",
+        // where KIND is one of "dylib", "framework", "static".
         let mut parts = s.splitn(2, '=');
         let kind = parts.next().unwrap();
         let (name, kind) = match (parts.next(), kind) {
@@ -1462,7 +1464,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
                                                  s));
             }
         };
-        (name.to_string(), kind)
+        let mut name_parts = name.splitn(2, ':');
+        let name = name_parts.next().unwrap();
+        let new_name = name_parts.next();
+        (name.to_string(), new_name.map(|n| n.to_string()), kind)
     }).collect();
 
     let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
@@ -1728,8 +1733,8 @@ mod dep_tracking {
     impl_dep_tracking_hash_for_sortable_vec_of!(String);
     impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
     impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
-    impl_dep_tracking_hash_for_sortable_vec_of!((String, cstore::NativeLibraryKind));
-
+    impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>,
+                                                 cstore::NativeLibraryKind));
     impl DepTrackingHash for SearchPaths {
         fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
             let mut elems: Vec<_> = self
@@ -1752,6 +1757,21 @@ mod dep_tracking {
         }
     }
 
+    impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3)
+        where T1: DepTrackingHash,
+              T2: DepTrackingHash,
+              T3: DepTrackingHash
+    {
+        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
+            Hash::hash(&0, hasher);
+            DepTrackingHash::hash(&self.0, hasher, error_format);
+            Hash::hash(&1, hasher);
+            DepTrackingHash::hash(&self.1, hasher, error_format);
+            Hash::hash(&2, hasher);
+            DepTrackingHash::hash(&self.2, hasher, error_format);
+        }
+    }
+
     // This is a stable hash because BTreeMap is a sorted container
     pub fn stable_hash(sub_hashes: BTreeMap<&'static str, &DepTrackingHash>,
                        hasher: &mut DefaultHasher,
@@ -2155,29 +2175,37 @@ mod tests {
         let mut v1 = super::basic_options();
         let mut v2 = super::basic_options();
         let mut v3 = super::basic_options();
+        let mut v4 = super::basic_options();
 
         // Reference
-        v1.libs = vec![(String::from("a"), cstore::NativeStatic),
-                       (String::from("b"), cstore::NativeFramework),
-                       (String::from("c"), cstore::NativeUnknown)];
+        v1.libs = vec![(String::from("a"), None, cstore::NativeStatic),
+                       (String::from("b"), None, cstore::NativeFramework),
+                       (String::from("c"), None, cstore::NativeUnknown)];
 
         // Change label
-        v2.libs = vec![(String::from("a"), cstore::NativeStatic),
-                       (String::from("X"), cstore::NativeFramework),
-                       (String::from("c"), cstore::NativeUnknown)];
+        v2.libs = vec![(String::from("a"), None, cstore::NativeStatic),
+                       (String::from("X"), None, cstore::NativeFramework),
+                       (String::from("c"), None, cstore::NativeUnknown)];
 
         // Change kind
-        v3.libs = vec![(String::from("a"), cstore::NativeStatic),
-                       (String::from("b"), cstore::NativeStatic),
-                       (String::from("c"), cstore::NativeUnknown)];
+        v3.libs = vec![(String::from("a"), None, cstore::NativeStatic),
+                       (String::from("b"), None, cstore::NativeStatic),
+                       (String::from("c"), None, cstore::NativeUnknown)];
+
+        // Change new-name
+        v4.libs = vec![(String::from("a"), None, cstore::NativeStatic),
+                       (String::from("b"), Some(String::from("X")), cstore::NativeFramework),
+                       (String::from("c"), None, cstore::NativeUnknown)];
 
         assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
+        assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
 
         // Check clone
         assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
         assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
         assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
+        assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
     }
 
     #[test]
@@ -2187,17 +2215,17 @@ mod tests {
         let mut v3 = super::basic_options();
 
         // Reference
-        v1.libs = vec![(String::from("a"), cstore::NativeStatic),
-                       (String::from("b"), cstore::NativeFramework),
-                       (String::from("c"), cstore::NativeUnknown)];
+        v1.libs = vec![(String::from("a"), None, cstore::NativeStatic),
+                       (String::from("b"), None, cstore::NativeFramework),
+                       (String::from("c"), None, cstore::NativeUnknown)];
 
-        v2.libs = vec![(String::from("b"), cstore::NativeFramework),
-                       (String::from("a"), cstore::NativeStatic),
-                       (String::from("c"), cstore::NativeUnknown)];
+        v2.libs = vec![(String::from("b"), None, cstore::NativeFramework),
+                       (String::from("a"), None, cstore::NativeStatic),
+                       (String::from("c"), None, cstore::NativeUnknown)];
 
-        v3.libs = vec![(String::from("c"), cstore::NativeUnknown),
-                       (String::from("a"), cstore::NativeStatic),
-                       (String::from("b"), cstore::NativeFramework)];
+        v3.libs = vec![(String::from("c"), None, cstore::NativeUnknown),
+                       (String::from("a"), None, cstore::NativeStatic),
+                       (String::from("b"), None, cstore::NativeFramework)];
 
         assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index d2592a3acee..a6b2fe471df 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -471,11 +471,9 @@ pub mod debuginfo {
 // generates an llvmdeps.rs file next to this one which will be
 // automatically updated whenever LLVM is updated to include an up-to-date
 // set of the libraries we need to link to LLVM for.
-#[link(name = "rustllvm", kind = "static")]
-#[cfg(not(cargobuild))]
-extern "C" {}
-
-#[linked_from = "rustllvm"] // not quite true but good enough
+#[cfg_attr(not(all(stage0,cargobuild)),
+           link(name = "rustllvm", kind = "static"))] // not quite true but good enough
+#[cfg_attr(stage0, linked_from = "rustllvm")]
 extern "C" {
     // Create and destroy contexts.
     pub fn LLVMContextCreate() -> ContextRef;
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 2fe13d1120f..a15edcd44be 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -27,7 +27,7 @@
 #![feature(concat_idents)]
 #![feature(libc)]
 #![feature(link_args)]
-#![feature(linked_from)]
+#![cfg_attr(stage0, feature(linked_from))]
 #![feature(staged_api)]
 #![cfg_attr(not(stage0), feature(rustc_private))]
 
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 2c266068fe8..d36242537b8 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -22,7 +22,7 @@ use rustc_back::PanicStrategy;
 use rustc::session::search_paths::PathKind;
 use rustc::middle;
 use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
-use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use rustc::util::nodemap::FxHashSet;
 use rustc::middle::cstore::NativeLibrary;
 use rustc::hir::map::Definitions;
 
@@ -52,7 +52,6 @@ pub struct CrateLoader<'a> {
     pub sess: &'a Session,
     cstore: &'a CStore,
     next_crate_num: CrateNum,
-    foreign_item_map: FxHashMap<String, Vec<ast::NodeId>>,
     local_crate_name: Symbol,
 }
 
@@ -114,6 +113,13 @@ fn register_native_lib(sess: &Session,
     cstore.add_used_library(lib);
 }
 
+fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
+    match lib.cfg {
+        Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
+        None => true,
+    }
+}
+
 // Extra info about a crate loaded for plugins or exported macros.
 struct ExtensionCrate {
     metadata: PMDSource,
@@ -148,7 +154,6 @@ impl<'a> CrateLoader<'a> {
             sess: sess,
             cstore: cstore,
             next_crate_num: cstore.next_crate_num(),
-            foreign_item_map: FxHashMap(),
             local_crate_name: Symbol::intern(local_crate_name),
         }
     }
@@ -292,7 +297,7 @@ impl<'a> CrateLoader<'a> {
 
         let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
 
-        let cmeta = Rc::new(cstore::CrateMetadata {
+        let mut cmeta = cstore::CrateMetadata {
             name: name,
             extern_crate: Cell::new(None),
             key_map: metadata.load_key_map(crate_root.index),
@@ -310,8 +315,18 @@ impl<'a> CrateLoader<'a> {
                 rlib: rlib,
                 rmeta: rmeta,
             },
-        });
+            dllimport_foreign_items: FxHashSet(),
+        };
 
+        let dllimports: Vec<_> = cmeta.get_native_libraries().iter()
+                            .filter(|lib| relevant_lib(self.sess, lib) &&
+                                          lib.kind == cstore::NativeLibraryKind::NativeUnknown)
+                            .flat_map(|lib| &lib.foreign_items)
+                            .map(|id| *id)
+                            .collect();
+        cmeta.dllimport_foreign_items.extend(dllimports);
+
+        let cmeta = Rc::new(cmeta);
         self.cstore.set_crate_data(cnum, cmeta.clone());
         (cnum, cmeta)
     }
@@ -640,18 +655,28 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn register_statically_included_foreign_items(&mut self) {
+    fn get_foreign_items_of_kind(&self, kind: cstore::NativeLibraryKind) -> Vec<DefIndex> {
+        let mut items = vec![];
         let libs = self.cstore.get_used_libraries();
-        for (foreign_lib, list) in self.foreign_item_map.iter() {
-            let is_static = libs.borrow().iter().any(|lib| {
-                lib.name == &**foreign_lib && lib.kind == cstore::NativeStatic
-            });
-            if is_static {
-                for id in list {
-                    self.cstore.add_statically_included_foreign_item(*id);
-                }
+        for lib in libs.borrow().iter() {
+            if relevant_lib(self.sess, lib) && lib.kind == kind {
+                items.extend(&lib.foreign_items);
             }
         }
+        items
+    }
+
+    fn register_statically_included_foreign_items(&mut self) {
+        for id in self.get_foreign_items_of_kind(cstore::NativeStatic) {
+            self.cstore.add_statically_included_foreign_item(id);
+        }
+    }
+
+    fn register_dllimport_foreign_items(&mut self) {
+        let mut dllimports = self.cstore.dllimport_foreign_items.borrow_mut();
+        for id in self.get_foreign_items_of_kind(cstore::NativeUnknown) {
+            dllimports.insert(id);
+        }
     }
 
     fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
@@ -861,7 +886,8 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
+    fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod,
+                           definitions: &Definitions) {
         if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
             return;
         }
@@ -912,24 +938,17 @@ impl<'a> CrateLoader<'a> {
             let cfg = cfg.map(|list| {
                 list[0].meta_item().unwrap().clone()
             });
+            let foreign_items = fm.items.iter()
+                .map(|it| definitions.opt_def_index(it.id).unwrap())
+                .collect();
             let lib = NativeLibrary {
                 name: n,
                 kind: kind,
                 cfg: cfg,
+                foreign_items: foreign_items,
             };
             register_native_lib(self.sess, self.cstore, Some(m.span), lib);
         }
-
-        // Finally, process the #[linked_from = "..."] attribute
-        for m in i.attrs.iter().filter(|a| a.check_name("linked_from")) {
-            let lib_name = match m.value_str() {
-                Some(name) => name,
-                None => continue,
-            };
-            let list = self.foreign_item_map.entry(lib_name.to_string())
-                                                    .or_insert(Vec::new());
-            list.extend(fm.items.iter().map(|it| it.id));
-        }
     }
 }
 
@@ -942,35 +961,76 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
             dump_crates(&self.cstore);
         }
 
-        for &(ref name, kind) in &self.sess.opts.libs {
-            let lib = NativeLibrary {
-                name: Symbol::intern(name),
-                kind: kind,
-                cfg: None,
-            };
-            register_native_lib(self.sess, self.cstore, None, lib);
+        // Process libs passed on the command line
+        // First, check for errors
+        let mut renames = FxHashSet();
+        for &(ref name, ref new_name, _) in &self.sess.opts.libs {
+            if let &Some(ref new_name) = new_name {
+                if new_name.is_empty() {
+                    self.sess.err(
+                        &format!("an empty renaming target was specified for library `{}`",name));
+                } else if !self.cstore.get_used_libraries().borrow().iter()
+                                                           .any(|lib| lib.name == name as &str) {
+                    self.sess.err(&format!("renaming of the library `{}` was specified, \
+                                            however this crate contains no #[link(...)] \
+                                            attributes referencing this library.", name));
+                } else if renames.contains(name) {
+                    self.sess.err(&format!("multiple renamings were specified for library `{}` .",
+                                            name));
+                } else {
+                    renames.insert(name);
+                }
+            }
+        }
+        // Update kind and, optionally, the name of all native libaries
+        // (there may be more than one) with the specified name.
+        for &(ref name, ref new_name, kind) in &self.sess.opts.libs {
+            let mut found = false;
+            for lib in self.cstore.get_used_libraries().borrow_mut().iter_mut() {
+                if lib.name == name as &str {
+                    lib.kind = kind;
+                    if let &Some(ref new_name) = new_name {
+                        lib.name = Symbol::intern(new_name);
+                    }
+                    found = true;
+                }
+            }
+            if !found {
+                // Add if not found
+                let new_name = new_name.as_ref().map(|s| &**s); // &Option<String> -> Option<&str>
+                let lib = NativeLibrary {
+                    name: Symbol::intern(new_name.unwrap_or(name)),
+                    kind: kind,
+                    cfg: None,
+                    foreign_items: Vec::new(),
+                };
+                register_native_lib(self.sess, self.cstore, None, lib);
+            }
         }
         self.register_statically_included_foreign_items();
+        self.register_dllimport_foreign_items();
     }
 
     fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
         match item.node {
-            ast::ItemKind::ExternCrate(_) => {}
-            ast::ItemKind::ForeignMod(ref fm) => return self.process_foreign_mod(item, fm),
-            _ => return,
-        }
-
-        let info = self.extract_crate_info(item).unwrap();
-        let (cnum, ..) = self.resolve_crate(
-            &None, info.ident, info.name, None, item.span, PathKind::Crate, info.dep_kind,
-        );
+            ast::ItemKind::ForeignMod(ref fm) => {
+                self.process_foreign_mod(item, fm, definitions)
+            },
+            ast::ItemKind::ExternCrate(_) => {
+                let info = self.extract_crate_info(item).unwrap();
+                let (cnum, ..) = self.resolve_crate(
+                    &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 len = definitions.def_path(def_id.index).data.len();
+                let def_id = definitions.opt_local_def_id(item.id).unwrap();
+                let len = definitions.def_path(def_id.index).data.len();
 
-        let extern_crate =
-            ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len };
-        self.update_extern_crate(cnum, extern_crate, &mut FxHashSet());
-        self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
+                let extern_crate =
+                    ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len };
+                self.update_extern_crate(cnum, extern_crate, &mut FxHashSet());
+                self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
+            }
+            _ => {}
+        }
     }
 }
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 73e03a45196..7700ebde181 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -15,13 +15,13 @@ use locator;
 use schema;
 
 use rustc::dep_graph::DepGraph;
-use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId};
 use rustc::hir::map::DefKey;
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::{DepKind, ExternCrate};
 use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc::util::nodemap::{FxHashMap, NodeMap, NodeSet, DefIdMap};
+use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap, DefIdMap};
 
 use std::cell::{RefCell, Cell};
 use std::rc::Rc;
@@ -31,7 +31,7 @@ use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
 use syntax_pos;
 
-pub use rustc::middle::cstore::{NativeLibrary, LinkagePreference};
+pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
 pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
 pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
 
@@ -84,6 +84,8 @@ pub struct CrateMetadata {
     pub source: CrateSource,
 
     pub proc_macros: Option<Vec<(ast::Name, Rc<SyntaxExtension>)>>,
+    // Foreign items imported from a dylib (Windows only)
+    pub dllimport_foreign_items: FxHashSet<DefIndex>,
 }
 
 pub struct CachedInlinedItem {
@@ -100,7 +102,8 @@ pub struct CStore {
     extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
     used_libraries: RefCell<Vec<NativeLibrary>>,
     used_link_args: RefCell<Vec<String>>,
-    statically_included_foreign_items: RefCell<NodeSet>,
+    statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
+    pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
     pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
     pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
     pub visible_parent_map: RefCell<DefIdMap<DefId>>,
@@ -114,7 +117,8 @@ impl CStore {
             extern_mod_crate_map: RefCell::new(FxHashMap()),
             used_libraries: RefCell::new(Vec::new()),
             used_link_args: RefCell::new(Vec::new()),
-            statically_included_foreign_items: RefCell::new(NodeSet()),
+            statically_included_foreign_items: RefCell::new(FxHashSet()),
+            dllimport_foreign_items: RefCell::new(FxHashSet()),
             visible_parent_map: RefCell::new(FxHashMap()),
             inlined_item_cache: RefCell::new(FxHashMap()),
             defid_for_inlined_node: RefCell::new(FxHashMap()),
@@ -246,12 +250,13 @@ impl CStore {
         self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
     }
 
-    pub fn add_statically_included_foreign_item(&self, id: ast::NodeId) {
+    pub fn add_statically_included_foreign_item(&self, id: DefIndex) {
         self.statically_included_foreign_items.borrow_mut().insert(id);
     }
 
-    pub fn do_is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool {
-        self.statically_included_foreign_items.borrow().contains(&id)
+    pub fn do_is_statically_included_foreign_item(&self, def_id: DefId) -> bool {
+        assert!(def_id.krate == LOCAL_CRATE);
+        self.statically_included_foreign_items.borrow().contains(&def_id.index)
     }
 
     pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index aca1d2f7612..2882efb75b0 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -19,7 +19,7 @@ use rustc::hir::def::{self, Def};
 use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 
 use rustc::dep_graph::DepNode;
 use rustc::hir::map as hir_map;
@@ -217,9 +217,17 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         self.get_crate_data(did.krate).is_foreign_item(did.index)
     }
 
-    fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool
+    fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool
     {
-        self.do_is_statically_included_foreign_item(id)
+        self.do_is_statically_included_foreign_item(def_id)
+    }
+
+    fn is_dllimport_foreign_item(&self, def_id: DefId) -> bool {
+        if def_id.krate == LOCAL_CRATE {
+            self.dllimport_foreign_items.borrow().contains(&def_id.index)
+        } else {
+            self.get_crate_data(def_id.krate).is_dllimport_foreign_item(def_id.index)
+        }
     }
 
     fn dylib_dependency_formats(&self, cnum: CrateNum)
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 43635eae76c..2a6063cc4bd 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1068,6 +1068,10 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
+    pub fn is_dllimport_foreign_item(&self, id: DefIndex) -> bool {
+        self.dllimport_foreign_items.contains(&id)
+    }
+
     pub fn is_defaulted_trait(&self, trait_id: DefIndex) -> bool {
         match self.entry(trait_id).kind {
             EntryKind::Trait(data) => data.decode(self).has_default_impl,
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 867e4dce19a..5b79f040d0f 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1536,7 +1536,8 @@ pub fn find_exported_symbols(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
         // let it through if it's included statically.
         match tcx.map.get(id) {
             hir_map::NodeForeignItem(..) => {
-                tcx.sess.cstore.is_statically_included_foreign_item(id)
+                let def_id = tcx.map.local_def_id(id);
+                tcx.sess.cstore.is_statically_included_foreign_item(def_id)
             }
 
             // Only consider nodes that actually have exported symbols.
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 7fb57dc19fc..d7e9f1372e0 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -637,7 +637,11 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
             }
         }
-
+        if ccx.use_dll_storage_attrs() && ccx.sess().cstore.is_dllimport_foreign_item(def_id) {
+            unsafe {
+                llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
+            }
+        }
         llfn
     };
 
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 4186721c122..730a4025a59 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -191,7 +191,12 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
                 llvm::set_thread_local(g, true);
             }
         }
-        if ccx.use_dll_storage_attrs() {
+        if ccx.use_dll_storage_attrs() && !ccx.sess().cstore.is_foreign_item(def_id) {
+            // This item is external but not foreign, i.e. it originates from an external Rust
+            // crate. Since we don't know whether this crate will be linked dynamically or
+            // statically in the final application, we always mark such symbols as 'dllimport'.
+            // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs to
+            // make things work.
             unsafe {
                 llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
             }
@@ -199,6 +204,12 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
         g
     };
 
+    if ccx.use_dll_storage_attrs() && ccx.sess().cstore.is_dllimport_foreign_item(def_id) {
+        // For foreign (native) libs we know the exact storage type to use.
+        unsafe {
+            llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
+        }
+    }
     ccx.instances().borrow_mut().insert(instance, g);
     ccx.statics().borrow_mut().insert(g, def_id);
     g
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 29854260899..72ea781bc22 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -132,7 +132,6 @@ declare_features! (
 
     (active, allocator, "1.0.0", Some(27389)),
     (active, fundamental, "1.0.0", Some(29635)),
-    (active, linked_from, "1.3.0", Some(29629)),
     (active, main, "1.0.0", Some(29634)),
     (active, needs_allocator, "1.4.0", Some(27389)),
     (active, on_unimplemented, "1.0.0", Some(29628)),
@@ -638,12 +637,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                         is an experimental feature",
                                        cfg_fn!(fundamental))),
 
-    ("linked_from", Normal, Gated(Stability::Unstable,
-                                  "linked_from",
-                                  "the `#[linked_from]` attribute \
-                                   is an experimental feature",
-                                  cfg_fn!(linked_from))),
-
     ("proc_macro_derive", Normal, Gated(Stability::Unstable,
                                         "proc_macro",
                                         "the `#[proc_macro_derive]` attribute \
diff --git a/src/test/codegen/dllimports/auxiliary/dummy.rs b/src/test/codegen/dllimports/auxiliary/dummy.rs
new file mode 100644
index 00000000000..06001c6b014
--- /dev/null
+++ b/src/test/codegen/dllimports/auxiliary/dummy.rs
@@ -0,0 +1,16 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+#![crate_type = "staticlib"]
+
+// Since codegen tests don't actually perform linking, this library doesn't need to export
+// any symbols.  It's here just to satisfy the compiler looking for a .lib file when processing
+// #[link(...)] attributes in wrapper.rs.
diff --git a/src/test/codegen/dllimports/auxiliary/wrapper.rs b/src/test/codegen/dllimports/auxiliary/wrapper.rs
new file mode 100644
index 00000000000..c03f88092e5
--- /dev/null
+++ b/src/test/codegen/dllimports/auxiliary/wrapper.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+#![crate_type = "rlib"]
+
+#[link(name = "dummy", kind="dylib")]
+extern "C" {
+    pub fn dylib_func2(x: i32) -> i32;
+    pub static dylib_global2: i32;
+}
+
+#[link(name = "dummy", kind="static")]
+extern "C" {
+    pub fn static_func2(x: i32) -> i32;
+    pub static static_global2: i32;
+}
diff --git a/src/test/codegen/dllimports/main.rs b/src/test/codegen/dllimports/main.rs
new file mode 100644
index 00000000000..64f516aa272
--- /dev/null
+++ b/src/test/codegen/dllimports/main.rs
@@ -0,0 +1,64 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test is for *-windows-msvc only.
+// ignore-gnu
+// ignore-android
+// ignore-bitrig
+// ignore-macos
+// ignore-dragonfly
+// ignore-freebsd
+// ignore-haiku
+// ignore-ios
+// ignore-linux
+// ignore-netbsd
+// ignore-openbsd
+// ignore-solaris
+// ignore-emscripten
+
+// aux-build:dummy.rs
+// aux-build:wrapper.rs
+
+extern crate wrapper;
+
+// Check that external symbols coming from foreign dylibs are adorned with 'dllimport',
+// whereas symbols coming from foreign staticlibs are not. (RFC-1717)
+
+// CHECK: @dylib_global1 = external dllimport local_unnamed_addr global i32
+// CHECK: @dylib_global2 = external dllimport local_unnamed_addr global i32
+// CHECK: @static_global1 = external local_unnamed_addr global i32
+// CHECK: @static_global2 = external local_unnamed_addr global i32
+
+// CHECK: declare dllimport i32 @dylib_func1(i32)
+// CHECK: declare dllimport i32 @dylib_func2(i32)
+// CHECK: declare i32 @static_func1(i32)
+// CHECK: declare i32 @static_func2(i32)
+
+#[link(name = "dummy", kind="dylib")]
+extern "C" {
+    pub fn dylib_func1(x: i32) -> i32;
+    pub static dylib_global1: i32;
+}
+
+#[link(name = "dummy", kind="static")]
+extern "C" {
+    pub fn static_func1(x: i32) -> i32;
+    pub static static_global1: i32;
+}
+
+fn main() {
+    unsafe {
+        dylib_func1(dylib_global1);
+        wrapper::dylib_func2(wrapper::dylib_global2);
+
+        static_func1(static_global1);
+        wrapper::static_func2(wrapper::static_global2);
+    }
+}
diff --git a/src/test/compile-fail/rfc1717/missing-link-attr.rs b/src/test/compile-fail/rfc1717/missing-link-attr.rs
new file mode 100644
index 00000000000..810efdedfd6
--- /dev/null
+++ b/src/test/compile-fail/rfc1717/missing-link-attr.rs
@@ -0,0 +1,14 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -l foo:bar
+// error-pattern: renaming of the library `foo` was specified
+
+#![crate_type = "lib"]
diff --git a/src/test/compile-fail/rfc1717/multiple-renames.rs b/src/test/compile-fail/rfc1717/multiple-renames.rs
new file mode 100644
index 00000000000..e75c1a14b24
--- /dev/null
+++ b/src/test/compile-fail/rfc1717/multiple-renames.rs
@@ -0,0 +1,17 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -l foo:bar -l foo:baz
+// error-pattern: multiple renamings were specified for library
+
+#![crate_type = "lib"]
+
+#[link(name = "foo")]
+extern "C" {}
diff --git a/src/test/compile-fail/rfc1717/rename-to-empty.rs b/src/test/compile-fail/rfc1717/rename-to-empty.rs
new file mode 100644
index 00000000000..ab8c238bc27
--- /dev/null
+++ b/src/test/compile-fail/rfc1717/rename-to-empty.rs
@@ -0,0 +1,17 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -l foo:
+// error-pattern: an empty renaming target was specified for library
+
+#![crate_type = "lib"]
+
+#[link(name = "foo")]
+extern "C" {}
diff --git a/src/test/run-make/c-static-dylib/foo.rs b/src/test/run-make/c-static-dylib/foo.rs
index 04253be71d4..44be5ac890d 100644
--- a/src/test/run-make/c-static-dylib/foo.rs
+++ b/src/test/run-make/c-static-dylib/foo.rs
@@ -10,7 +10,7 @@
 
 #![crate_type = "dylib"]
 
-#[link(name = "cfoo")]
+#[link(name = "cfoo", kind = "static")]
 extern {
     fn foo();
 }
diff --git a/src/test/run-make/c-static-rlib/foo.rs b/src/test/run-make/c-static-rlib/foo.rs
index a1f01bd2b62..cbd7b020bd8 100644
--- a/src/test/run-make/c-static-rlib/foo.rs
+++ b/src/test/run-make/c-static-rlib/foo.rs
@@ -10,7 +10,7 @@
 
 #![crate_type = "rlib"]
 
-#[link(name = "cfoo")]
+#[link(name = "cfoo", kind = "static")]
 extern {
     fn foo();
 }
diff --git a/src/test/run-make/extern-fn-generic/test.rs b/src/test/run-make/extern-fn-generic/test.rs
index ee0485683ec..8f5ff091b3b 100644
--- a/src/test/run-make/extern-fn-generic/test.rs
+++ b/src/test/run-make/extern-fn-generic/test.rs
@@ -12,7 +12,7 @@ extern crate testcrate;
 
 extern "C" fn bar<T>(ts: testcrate::TestStruct<T>) -> T { ts.y }
 
-#[link(name = "test")]
+#[link(name = "test", kind = "static")]
 extern {
     fn call(c: extern "C" fn(testcrate::TestStruct<i32>) -> i32) -> i32;
 }
diff --git a/src/test/run-make/extern-fn-generic/testcrate.rs b/src/test/run-make/extern-fn-generic/testcrate.rs
index 5fd61bb419c..d02c05047c0 100644
--- a/src/test/run-make/extern-fn-generic/testcrate.rs
+++ b/src/test/run-make/extern-fn-generic/testcrate.rs
@@ -18,7 +18,7 @@ pub struct TestStruct<T> {
 
 pub extern "C" fn foo<T>(ts: TestStruct<T>) -> T { ts.y }
 
-#[link(name = "test")]
+#[link(name = "test", kind = "static")]
 extern {
     pub fn call(c: extern "C" fn(TestStruct<i32>) -> i32) -> i32;
 }
diff --git a/src/test/run-make/interdependent-c-libraries/bar.rs b/src/test/run-make/interdependent-c-libraries/bar.rs
index 88fc98615f0..1963976b4b0 100644
--- a/src/test/run-make/interdependent-c-libraries/bar.rs
+++ b/src/test/run-make/interdependent-c-libraries/bar.rs
@@ -12,7 +12,7 @@
 
 extern crate foo;
 
-#[link(name = "bar")]
+#[link(name = "bar", kind = "static")]
 extern {
     fn bar();
 }
diff --git a/src/test/run-make/interdependent-c-libraries/foo.rs b/src/test/run-make/interdependent-c-libraries/foo.rs
index f94c6edb97d..7a0fe6bb18f 100644
--- a/src/test/run-make/interdependent-c-libraries/foo.rs
+++ b/src/test/run-make/interdependent-c-libraries/foo.rs
@@ -10,7 +10,7 @@
 
 #![crate_type = "rlib"]
 
-#[link(name = "foo")]
+#[link(name = "foo", kind = "static")]
 extern {
     fn foo();
 }
diff --git a/src/test/run-make/issue-15460/foo.rs b/src/test/run-make/issue-15460/foo.rs
index 8b96fe36824..6917fa55579 100644
--- a/src/test/run-make/issue-15460/foo.rs
+++ b/src/test/run-make/issue-15460/foo.rs
@@ -8,11 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(linked_from)]
 #![crate_type = "dylib"]
 
 #[link(name = "foo", kind = "static")]
-#[linked_from = "foo"]
 extern {
     pub fn foo();
 }
diff --git a/src/test/run-make/issue-25581/test.rs b/src/test/run-make/issue-25581/test.rs
index e2e86df59cd..6717d16cb7c 100644
--- a/src/test/run-make/issue-25581/test.rs
+++ b/src/test/run-make/issue-25581/test.rs
@@ -12,7 +12,7 @@
 
 extern crate libc;
 
-#[link(name = "test")]
+#[link(name = "test", kind = "static")]
 extern {
     fn slice_len(s: &[u8]) -> libc::size_t;
     fn slice_elem(s: &[u8], idx: libc::size_t) -> u8;
diff --git a/src/test/run-make/link-path-order/main.rs b/src/test/run-make/link-path-order/main.rs
index 450460cf192..aaac3927f1c 100644
--- a/src/test/run-make/link-path-order/main.rs
+++ b/src/test/run-make/link-path-order/main.rs
@@ -12,7 +12,7 @@
 
 extern crate libc;
 
-#[link(name="foo")]
+#[link(name="foo", kind = "static")]
 extern {
     fn should_return_one() -> libc::c_int;
 }
diff --git a/src/test/run-pass/abi-sysv64-arg-passing.rs b/src/test/run-pass/abi-sysv64-arg-passing.rs
index 989155bdfd9..23dd0603184 100644
--- a/src/test/run-pass/abi-sysv64-arg-passing.rs
+++ b/src/test/run-pass/abi-sysv64-arg-passing.rs
@@ -98,7 +98,7 @@ mod tests {
     #[derive(Copy, Clone)]
     pub struct Floats { a: f64, b: u8, c: f64 }
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern "sysv64" {
         pub fn rust_int8_to_int32(_: i8) -> i32;
         pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
diff --git a/src/test/run-pass/anon-extern-mod.rs b/src/test/run-pass/anon-extern-mod.rs
index e96b0cc1442..208b4df3c3e 100644
--- a/src/test/run-pass/anon-extern-mod.rs
+++ b/src/test/run-pass/anon-extern-mod.rs
@@ -14,7 +14,7 @@
 
 extern crate libc;
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     fn rust_get_test_int() -> libc::intptr_t;
 }
diff --git a/src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs
index 197fb9a6d01..741ce351da3 100644
--- a/src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ b/src/test/run-pass/auxiliary/anon-extern-mod-cross-crate-1.rs
@@ -13,7 +13,7 @@
 
 extern crate libc;
 
-#[link(name="rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_get_test_int() -> libc::intptr_t;
 }
diff --git a/src/test/run-pass/auxiliary/extern-crosscrate-source.rs b/src/test/run-pass/auxiliary/extern-crosscrate-source.rs
index fc2e328f686..150dffeea88 100644
--- a/src/test/run-pass/auxiliary/extern-crosscrate-source.rs
+++ b/src/test/run-pass/auxiliary/extern-crosscrate-source.rs
@@ -17,7 +17,7 @@ extern crate libc;
 pub mod rustrt {
     extern crate libc;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
                              data: libc::uintptr_t)
diff --git a/src/test/run-pass/auxiliary/foreign_lib.rs b/src/test/run-pass/auxiliary/foreign_lib.rs
index 460d0a0088c..cef36274c62 100644
--- a/src/test/run-pass/auxiliary/foreign_lib.rs
+++ b/src/test/run-pass/auxiliary/foreign_lib.rs
@@ -15,7 +15,7 @@
 pub mod rustrt {
     extern crate libc;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
diff --git a/src/test/run-pass/auxiliary/issue-25185-1.rs b/src/test/run-pass/auxiliary/issue-25185-1.rs
index 1ec29501b76..b9da39cbbcb 100644
--- a/src/test/run-pass/auxiliary/issue-25185-1.rs
+++ b/src/test/run-pass/auxiliary/issue-25185-1.rs
@@ -10,12 +10,9 @@
 
 // no-prefer-dynamic
 
-#![feature(linked_from)]
-
 #![crate_type = "rlib"]
 
 #[link(name = "rust_test_helpers", kind = "static")]
-#[linked_from = "rust_test_helpers"]
 extern {
     pub fn rust_dbg_extern_identity_u32(u: u32) -> u32;
 }
diff --git a/src/test/run-pass/c-stack-as-value.rs b/src/test/run-pass/c-stack-as-value.rs
index b678f149fa2..5319693405b 100644
--- a/src/test/run-pass/c-stack-as-value.rs
+++ b/src/test/run-pass/c-stack-as-value.rs
@@ -15,7 +15,7 @@
 mod rustrt {
     extern crate libc;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
diff --git a/src/test/run-pass/cabi-int-widening.rs b/src/test/run-pass/cabi-int-widening.rs
index c7a22759333..bf94dd17882 100644
--- a/src/test/run-pass/cabi-int-widening.rs
+++ b/src/test/run-pass/cabi-int-widening.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     fn rust_int8_to_int32(_: i8) -> i32;
 }
diff --git a/src/test/run-pass/extern-call-deep.rs b/src/test/run-pass/extern-call-deep.rs
index 2138b12fb12..6a9da767ad6 100644
--- a/src/test/run-pass/extern-call-deep.rs
+++ b/src/test/run-pass/extern-call-deep.rs
@@ -15,7 +15,7 @@ extern crate libc;
 mod rustrt {
     extern crate libc;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
                              data: libc::uintptr_t)
diff --git a/src/test/run-pass/extern-call-deep2.rs b/src/test/run-pass/extern-call-deep2.rs
index 1a0191b7053..3bdc8c18864 100644
--- a/src/test/run-pass/extern-call-deep2.rs
+++ b/src/test/run-pass/extern-call-deep2.rs
@@ -18,7 +18,7 @@ use std::thread;
 mod rustrt {
     extern crate libc;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
                              data: libc::uintptr_t)
diff --git a/src/test/run-pass/extern-call-indirect.rs b/src/test/run-pass/extern-call-indirect.rs
index 4f1abbeb5c7..256eedccb8b 100644
--- a/src/test/run-pass/extern-call-indirect.rs
+++ b/src/test/run-pass/extern-call-indirect.rs
@@ -15,7 +15,7 @@ extern crate libc;
 mod rustrt {
     extern crate libc;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
                              data: libc::uintptr_t)
diff --git a/src/test/run-pass/extern-call-scrub.rs b/src/test/run-pass/extern-call-scrub.rs
index 1beb6d3519a..a27474dcf86 100644
--- a/src/test/run-pass/extern-call-scrub.rs
+++ b/src/test/run-pass/extern-call-scrub.rs
@@ -22,7 +22,7 @@ use std::thread;
 mod rustrt {
     extern crate libc;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t,
                              data: libc::uintptr_t)
diff --git a/src/test/run-pass/extern-pass-TwoU16s.rs b/src/test/run-pass/extern-pass-TwoU16s.rs
index 9d304ea9e10..afdd53db775 100644
--- a/src/test/run-pass/extern-pass-TwoU16s.rs
+++ b/src/test/run-pass/extern-pass-TwoU16s.rs
@@ -16,7 +16,7 @@ pub struct TwoU16s {
     one: u16, two: u16
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s;
 }
diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs
index 8dae0473fd5..035084ae9bd 100644
--- a/src/test/run-pass/extern-pass-TwoU32s.rs
+++ b/src/test/run-pass/extern-pass-TwoU32s.rs
@@ -16,7 +16,7 @@ pub struct TwoU32s {
     one: u32, two: u32
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s;
 }
diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs
index 14aeea34657..cb1a4d27825 100644
--- a/src/test/run-pass/extern-pass-TwoU64s.rs
+++ b/src/test/run-pass/extern-pass-TwoU64s.rs
@@ -16,7 +16,7 @@ pub struct TwoU64s {
     one: u64, two: u64
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
 }
diff --git a/src/test/run-pass/extern-pass-TwoU8s.rs b/src/test/run-pass/extern-pass-TwoU8s.rs
index 75a109e4429..657348c99aa 100644
--- a/src/test/run-pass/extern-pass-TwoU8s.rs
+++ b/src/test/run-pass/extern-pass-TwoU8s.rs
@@ -16,7 +16,7 @@ pub struct TwoU8s {
     one: u8, two: u8
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s;
 }
diff --git a/src/test/run-pass/extern-pass-char.rs b/src/test/run-pass/extern-pass-char.rs
index e75aa2d72c9..9042aed6639 100644
--- a/src/test/run-pass/extern-pass-char.rs
+++ b/src/test/run-pass/extern-pass-char.rs
@@ -11,7 +11,7 @@
 // Test a function that takes/returns a u8.
 
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
 }
diff --git a/src/test/run-pass/extern-pass-double.rs b/src/test/run-pass/extern-pass-double.rs
index e92f9b6a1a1..38d29180fbc 100644
--- a/src/test/run-pass/extern-pass-double.rs
+++ b/src/test/run-pass/extern-pass-double.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_identity_double(v: f64) -> f64;
 }
diff --git a/src/test/run-pass/extern-pass-empty.rs b/src/test/run-pass/extern-pass-empty.rs
index 801a3c40ab4..cce7dc5bf32 100644
--- a/src/test/run-pass/extern-pass-empty.rs
+++ b/src/test/run-pass/extern-pass-empty.rs
@@ -30,7 +30,7 @@ struct ManyInts {
 
 struct Empty;
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
 }
diff --git a/src/test/run-pass/extern-pass-u32.rs b/src/test/run-pass/extern-pass-u32.rs
index 0753ea1bcfe..ed254ac46f2 100644
--- a/src/test/run-pass/extern-pass-u32.rs
+++ b/src/test/run-pass/extern-pass-u32.rs
@@ -11,7 +11,7 @@
 // Test a function that takes/returns a u32.
 
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_identity_u32(v: u32) -> u32;
 }
diff --git a/src/test/run-pass/extern-pass-u64.rs b/src/test/run-pass/extern-pass-u64.rs
index 89faa3bb471..6fc630e6d7e 100644
--- a/src/test/run-pass/extern-pass-u64.rs
+++ b/src/test/run-pass/extern-pass-u64.rs
@@ -11,7 +11,7 @@
 // Test a call to a function that takes/returns a u64.
 
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
 }
diff --git a/src/test/run-pass/extern-return-TwoU16s.rs b/src/test/run-pass/extern-return-TwoU16s.rs
index 3c58646e0c3..ec1c6130e7a 100644
--- a/src/test/run-pass/extern-return-TwoU16s.rs
+++ b/src/test/run-pass/extern-return-TwoU16s.rs
@@ -13,7 +13,7 @@ pub struct TwoU16s {
     one: u16, two: u16
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s;
 }
diff --git a/src/test/run-pass/extern-return-TwoU32s.rs b/src/test/run-pass/extern-return-TwoU32s.rs
index 0eb6be2d687..e829e993052 100644
--- a/src/test/run-pass/extern-return-TwoU32s.rs
+++ b/src/test/run-pass/extern-return-TwoU32s.rs
@@ -13,7 +13,7 @@ pub struct TwoU32s {
     one: u32, two: u32
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
 }
diff --git a/src/test/run-pass/extern-return-TwoU64s.rs b/src/test/run-pass/extern-return-TwoU64s.rs
index d5eab86351e..ef7325b33fe 100644
--- a/src/test/run-pass/extern-return-TwoU64s.rs
+++ b/src/test/run-pass/extern-return-TwoU64s.rs
@@ -13,7 +13,7 @@ pub struct TwoU64s {
     one: u64, two: u64
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s;
 }
diff --git a/src/test/run-pass/extern-return-TwoU8s.rs b/src/test/run-pass/extern-return-TwoU8s.rs
index d8f476bcd0c..46f2e81a556 100644
--- a/src/test/run-pass/extern-return-TwoU8s.rs
+++ b/src/test/run-pass/extern-return-TwoU8s.rs
@@ -13,7 +13,7 @@ pub struct TwoU8s {
     one: u8, two: u8
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s;
 }
diff --git a/src/test/run-pass/foreign-call-no-runtime.rs b/src/test/run-pass/foreign-call-no-runtime.rs
index ca118899798..697e9074c44 100644
--- a/src/test/run-pass/foreign-call-no-runtime.rs
+++ b/src/test/run-pass/foreign-call-no-runtime.rs
@@ -18,7 +18,7 @@ extern crate libc;
 use std::mem;
 use std::thread;
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t),
                      data: libc::uintptr_t) -> libc::uintptr_t;
diff --git a/src/test/run-pass/foreign-fn-with-byval.rs b/src/test/run-pass/foreign-fn-with-byval.rs
index d3d872620c3..2d4542540e7 100644
--- a/src/test/run-pass/foreign-fn-with-byval.rs
+++ b/src/test/run-pass/foreign-fn-with-byval.rs
@@ -16,7 +16,7 @@ pub struct S {
     z: u64,
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     pub fn get_x(x: S) -> u64;
     pub fn get_y(x: S) -> u64;
diff --git a/src/test/run-pass/foreign-no-abi.rs b/src/test/run-pass/foreign-no-abi.rs
index a9b3f60566d..979e57eba9d 100644
--- a/src/test/run-pass/foreign-no-abi.rs
+++ b/src/test/run-pass/foreign-no-abi.rs
@@ -17,7 +17,7 @@
 mod rustrt {
     extern crate libc;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_get_test_int() -> libc::intptr_t;
     }
diff --git a/src/test/run-pass/issue-28676.rs b/src/test/run-pass/issue-28676.rs
index b8d43c392dd..8f83e51f0a0 100644
--- a/src/test/run-pass/issue-28676.rs
+++ b/src/test/run-pass/issue-28676.rs
@@ -15,7 +15,7 @@ pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
 mod rustrt {
     use super::Quad;
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn get_c_many_params(_: *const (), _: *const (),
                                  _: *const (), _: *const (), f: Quad) -> u64;
diff --git a/src/test/run-pass/mir_trans_calls_variadic.rs b/src/test/run-pass/mir_trans_calls_variadic.rs
index 4e06738da4f..e4d528e80e1 100644
--- a/src/test/run-pass/mir_trans_calls_variadic.rs
+++ b/src/test/run-pass/mir_trans_calls_variadic.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     fn rust_interesting_average(_: i64, ...) -> f64;
 }
diff --git a/src/test/compile-fail/feature-gate-linked-from.rs b/src/test/run-pass/rfc1717/auxiliary/clibrary.rs
index 8705684111e..7438ba21bfc 100644
--- a/src/test/compile-fail/feature-gate-linked-from.rs
+++ b/src/test/run-pass/rfc1717/auxiliary/clibrary.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[linked_from = "foo"] //~ ERROR experimental feature
-extern {
-    fn foo();
-}
+// no-prefer-dynamic
+#![crate_type = "staticlib"]
 
-fn main() {}
+#[no_mangle]
+pub extern "C" fn foo(x:i32) -> i32 { x }
diff --git a/src/test/run-pass/rfc1717/library-override.rs b/src/test/run-pass/rfc1717/library-override.rs
new file mode 100644
index 00000000000..d6ef96c5add
--- /dev/null
+++ b/src/test/run-pass/rfc1717/library-override.rs
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:clibrary.rs
+// compile-flags: -lstatic=wronglibrary:clibrary
+
+#[link(name = "wronglibrary", kind = "dylib")]
+extern "C" {
+    pub fn foo(x:i32) -> i32;
+}
+
+fn main() {
+    unsafe {
+        foo(42);
+    }
+}
diff --git a/src/test/run-pass/segfault-no-out-of-stack.rs b/src/test/run-pass/segfault-no-out-of-stack.rs
index df64d7140b4..0f98cfe27f6 100644
--- a/src/test/run-pass/segfault-no-out-of-stack.rs
+++ b/src/test/run-pass/segfault-no-out-of-stack.rs
@@ -17,7 +17,7 @@ extern crate libc;
 use std::process::{Command, ExitStatus};
 use std::env;
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     fn rust_get_null_ptr() -> *mut ::libc::c_char;
 }
diff --git a/src/test/run-pass/static-mut-foreign.rs b/src/test/run-pass/static-mut-foreign.rs
index 4dcb82c4b43..24d58487f06 100644
--- a/src/test/run-pass/static-mut-foreign.rs
+++ b/src/test/run-pass/static-mut-foreign.rs
@@ -17,7 +17,7 @@
 
 extern crate libc;
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     static mut rust_dbg_static_mut: libc::c_int;
     pub fn rust_dbg_static_mut_check_four();
diff --git a/src/test/run-pass/struct-return.rs b/src/test/run-pass/struct-return.rs
index 6f23263790c..3d4601ad0cf 100644
--- a/src/test/run-pass/struct-return.rs
+++ b/src/test/run-pass/struct-return.rs
@@ -18,7 +18,7 @@ pub struct Floats { a: f64, b: u8, c: f64 }
 mod rustrt {
     use super::{Floats, Quad};
 
-    #[link(name = "rust_test_helpers")]
+    #[link(name = "rust_test_helpers", kind = "static")]
     extern {
         pub fn rust_dbg_abi_1(q: Quad) -> Quad;
         pub fn rust_dbg_abi_2(f: Floats) -> Floats;
diff --git a/src/test/run-pass/union/union-c-interop.rs b/src/test/run-pass/union/union-c-interop.rs
index bea4d5f923e..13dfd414615 100644
--- a/src/test/run-pass/union/union-c-interop.rs
+++ b/src/test/run-pass/union/union-c-interop.rs
@@ -25,7 +25,7 @@ union LARGE_INTEGER {
   QuadPart: u64,
 }
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
     fn increment_all_parts(_: LARGE_INTEGER) -> LARGE_INTEGER;
 }
diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs
index 0131563d36d..ec6261febc5 100644
--- a/src/test/run-pass/variadic-ffi.rs
+++ b/src/test/run-pass/variadic-ffi.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[link(name = "rust_test_helpers")]
+#[link(name = "rust_test_helpers", kind = "static")]
 extern {
     fn rust_interesting_average(_: u64, ...) -> f64;
 }