about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-01-22 03:42:24 +0000
committerbors <bors@rust-lang.org>2017-01-22 03:42:24 +0000
commite5b0829bb06969b69a82527253a393e5c500c324 (patch)
tree5d1239898227ea3f7832280c7a6a7a3f8261af67
parent1b063750343601167f3d061a913172db2a0c2708 (diff)
parent191abc42642c29f589a34e7f6cdebd081c373138 (diff)
downloadrust-e5b0829bb06969b69a82527253a393e5c500c324.tar.gz
rust-e5b0829bb06969b69a82527253a393e5c500c324.zip
Auto merge of #39060 - jseyfried:improve_unused, r=nrc
Improve unused `extern crate` and unused `#[macro_use]` warnings

This PR
 - adds `unused_imports` warnings for unused `#[macro_use] extern crate` macro imports,
 - improves `unused_extern_crates` warnings (avoids false negatives), and
 - removes unused `#[macro_use]` imports and unused `extern crate`s.

r? @nrc
-rw-r--r--src/Cargo.lock17
-rw-r--r--src/libproc_macro_plugin/Cargo.toml1
-rw-r--r--src/libproc_macro_plugin/lib.rs1
-rw-r--r--src/libproc_macro_tokens/Cargo.toml2
-rw-r--r--src/libproc_macro_tokens/build.rs3
-rw-r--r--src/libproc_macro_tokens/lib.rs2
-rw-r--r--src/libproc_macro_tokens/parse.rs2
-rw-r--r--src/librustc/Cargo.toml1
-rw-r--r--src/librustc/lib.rs9
-rw-r--r--src/librustc_const_eval/Cargo.toml1
-rw-r--r--src/librustc_const_eval/lib.rs1
-rw-r--r--src/librustc_const_math/Cargo.toml1
-rw-r--r--src/librustc_const_math/lib.rs3
-rw-r--r--src/librustc_driver/Cargo.toml1
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustc_errors/Cargo.toml2
-rw-r--r--src/librustc_errors/lib.rs7
-rw-r--r--src/librustc_incremental/Cargo.toml1
-rw-r--r--src/librustc_incremental/lib.rs4
-rw-r--r--src/librustc_lint/lib.rs1
-rw-r--r--src/librustc_mir/Cargo.toml1
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_plugin/Cargo.toml2
-rw-r--r--src/librustc_plugin/lib.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs50
-rw-r--r--src/librustc_resolve/check_unused.rs32
-rw-r--r--src/librustc_resolve/lib.rs11
-rw-r--r--src/librustc_resolve/macros.rs16
-rw-r--r--src/librustc_resolve/resolve_imports.rs4
-rw-r--r--src/librustc_trans/Cargo.toml3
-rw-r--r--src/librustc_trans/lib.rs4
-rw-r--r--src/libserialize/Cargo.toml1
-rw-r--r--src/libserialize/lib.rs7
-rw-r--r--src/libsyntax/lib.rs4
-rw-r--r--src/test/compile-fail/imports/unused-macro-use.rs21
-rw-r--r--src/test/compile-fail/lint-unused-extern-crate.rs7
-rw-r--r--src/tools/cargotest/main.rs2
38 files changed, 104 insertions, 127 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index d153945dc09..2c10272916f 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -212,16 +212,13 @@ dependencies = [
  "proc_macro_tokens 0.0.0",
  "rustc_plugin 0.0.0",
  "syntax 0.0.0",
- "syntax_pos 0.0.0",
 ]
 
 [[package]]
 name = "proc_macro_tokens"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
  "syntax 0.0.0",
- "syntax_pos 0.0.0",
 ]
 
 [[package]]
@@ -240,7 +237,6 @@ name = "rustc"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "flate 0.0.0",
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
  "log 0.0.0",
@@ -310,7 +306,6 @@ dependencies = [
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_i128 0.0.0",
- "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -319,7 +314,6 @@ dependencies = [
 name = "rustc_const_math"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
  "rustc_i128 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
@@ -339,7 +333,6 @@ name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "flate 0.0.0",
  "graphviz 0.0.0",
  "log 0.0.0",
  "proc_macro_plugin 0.0.0",
@@ -371,8 +364,6 @@ dependencies = [
 name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
- "serialize 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
@@ -388,7 +379,6 @@ dependencies = [
  "log 0.0.0",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
- "rustc_i128 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -443,7 +433,6 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.0.0",
  "rustc 0.0.0",
- "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
  "rustc_const_eval 0.0.0",
  "rustc_const_math 0.0.0",
@@ -474,10 +463,8 @@ version = "0.0.0"
 name = "rustc_plugin"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
- "rustc_bitflags 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_metadata 0.0.0",
  "syntax 0.0.0",
@@ -520,9 +507,7 @@ dependencies = [
 name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
- "arena 0.0.0",
  "flate 0.0.0",
- "graphviz 0.0.0",
  "log 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
@@ -535,7 +520,6 @@ dependencies = [
  "rustc_incremental 0.0.0",
  "rustc_llvm 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
- "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -585,7 +569,6 @@ dependencies = [
 name = "serialize"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
  "rustc_i128 0.0.0",
 ]
 
diff --git a/src/libproc_macro_plugin/Cargo.toml b/src/libproc_macro_plugin/Cargo.toml
index 4bc3f488d32..33fd814cd5f 100644
--- a/src/libproc_macro_plugin/Cargo.toml
+++ b/src/libproc_macro_plugin/Cargo.toml
@@ -11,5 +11,4 @@ crate-type = ["dylib"]
 log = { path = "../liblog" }
 rustc_plugin = { path = "../librustc_plugin" }
 syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
 proc_macro_tokens = { path = "../libproc_macro_tokens" }
diff --git a/src/libproc_macro_plugin/lib.rs b/src/libproc_macro_plugin/lib.rs
index 0a7d3525848..9d8bb7fa0f5 100644
--- a/src/libproc_macro_plugin/lib.rs
+++ b/src/libproc_macro_plugin/lib.rs
@@ -88,7 +88,6 @@
 
 extern crate rustc_plugin;
 extern crate syntax;
-extern crate syntax_pos;
 extern crate proc_macro_tokens;
 #[macro_use] extern crate log;
 
diff --git a/src/libproc_macro_tokens/Cargo.toml b/src/libproc_macro_tokens/Cargo.toml
index b4365e4fb26..2cec4d7af54 100644
--- a/src/libproc_macro_tokens/Cargo.toml
+++ b/src/libproc_macro_tokens/Cargo.toml
@@ -10,5 +10,3 @@ crate-type = ["dylib"]
 
 [dependencies]
 syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
-log = { path = "../liblog" }
diff --git a/src/libproc_macro_tokens/build.rs b/src/libproc_macro_tokens/build.rs
index 89c84b6bc22..18aa60f9df1 100644
--- a/src/libproc_macro_tokens/build.rs
+++ b/src/libproc_macro_tokens/build.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern crate syntax;
-extern crate syntax_pos;
-
 use syntax::ast::Ident;
 use syntax::codemap::DUMMY_SP;
 use syntax::parse::token::{self, Token};
diff --git a/src/libproc_macro_tokens/lib.rs b/src/libproc_macro_tokens/lib.rs
index 0dd9aaab1c6..e20ed689915 100644
--- a/src/libproc_macro_tokens/lib.rs
+++ b/src/libproc_macro_tokens/lib.rs
@@ -58,8 +58,6 @@
 #![feature(rustc_private)]
 
 extern crate syntax;
-extern crate syntax_pos;
-#[macro_use] extern crate log;
 
 pub mod build;
 pub mod parse;
diff --git a/src/libproc_macro_tokens/parse.rs b/src/libproc_macro_tokens/parse.rs
index 5ab4fcd5dab..73268d0e662 100644
--- a/src/libproc_macro_tokens/parse.rs
+++ b/src/libproc_macro_tokens/parse.rs
@@ -10,8 +10,6 @@
 
 //! Parsing utilities for writing procedural macros.
 
-extern crate syntax;
-
 use syntax::parse::{ParseSess, filemap_to_tts};
 use syntax::tokenstream::TokenStream;
 
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 51494885e73..3c455eb0501 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -10,7 +10,6 @@ crate-type = ["dylib"]
 
 [dependencies]
 arena = { path = "../libarena" }
-flate = { path = "../libflate" }
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 log = { path = "../liblog" }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 151d7cd17ab..619a3e995c3 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -26,7 +26,6 @@
 #![feature(associated_consts)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(collections)]
 #![feature(conservative_impl_trait)]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
@@ -39,11 +38,9 @@
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
-#![cfg_attr(test, feature(test))]
 
 extern crate arena;
 extern crate core;
-extern crate flate;
 extern crate fmt_macros;
 extern crate getopts;
 extern crate graphviz;
@@ -52,12 +49,11 @@ extern crate rustc_llvm as llvm;
 extern crate rustc_back;
 extern crate rustc_data_structures;
 extern crate serialize;
-extern crate collections;
 extern crate rustc_const_math;
 extern crate rustc_errors as errors;
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
-#[macro_use] extern crate syntax_pos;
+extern crate syntax_pos;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
 
 extern crate serialize as rustc_serialize; // used by deriving
@@ -65,9 +61,6 @@ extern crate serialize as rustc_serialize; // used by deriving
 // SNAP:
 extern crate rustc_i128;
 
-#[cfg(test)]
-extern crate test;
-
 #[macro_use]
 mod macros;
 
diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml
index 7148e181bbd..ff028c202a8 100644
--- a/src/librustc_const_eval/Cargo.toml
+++ b/src/librustc_const_eval/Cargo.toml
@@ -11,7 +11,6 @@ crate-type = ["dylib"]
 [dependencies]
 arena = { path = "../libarena" }
 log = { path = "../liblog" }
-serialize = { path = "../libserialize" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs
index 67b4efdbd1f..2b6f487c2c9 100644
--- a/src/librustc_const_eval/lib.rs
+++ b/src/librustc_const_eval/lib.rs
@@ -40,7 +40,6 @@ extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate graphviz;
 extern crate syntax_pos;
-extern crate serialize as rustc_serialize; // used by deriving
 
 extern crate rustc_i128;
 
diff --git a/src/librustc_const_math/Cargo.toml b/src/librustc_const_math/Cargo.toml
index 3d7a4865e45..e6db1557fbe 100644
--- a/src/librustc_const_math/Cargo.toml
+++ b/src/librustc_const_math/Cargo.toml
@@ -9,7 +9,6 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-log = { path = "../liblog" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs
index cd933c00599..d40a6aa32fd 100644
--- a/src/librustc_const_math/lib.rs
+++ b/src/librustc_const_math/lib.rs
@@ -28,8 +28,7 @@
 #![feature(const_fn)]
 #![cfg_attr(not(stage0), feature(i128))]
 
-#[macro_use] extern crate log;
-#[macro_use] extern crate syntax;
+extern crate syntax;
 
 // SNAP: remove use of this crate
 extern crate rustc_i128;
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 99d3e155e89..caa5c8b7e00 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -10,7 +10,6 @@ crate-type = ["dylib"]
 
 [dependencies]
 arena = { path = "../libarena" }
-flate = { path = "../libflate" }
 graphviz = { path = "../libgraphviz" }
 log = { path = "../liblog" }
 proc_macro_plugin = { path = "../libproc_macro_plugin" }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 48eb6f68564..0ecd12b3a90 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -32,7 +32,6 @@
 #![feature(staged_api)]
 
 extern crate arena;
-extern crate flate;
 extern crate getopts;
 extern crate graphviz;
 extern crate libc;
@@ -57,7 +56,6 @@ extern crate serialize;
 extern crate rustc_llvm as llvm;
 #[macro_use]
 extern crate log;
-#[macro_use]
 extern crate syntax;
 extern crate syntax_ext;
 extern crate syntax_pos;
diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml
index c92e4d8f5ab..2ba1f501a63 100644
--- a/src/librustc_errors/Cargo.toml
+++ b/src/librustc_errors/Cargo.toml
@@ -9,6 +9,4 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-log = { path = "../liblog" }
-serialize = { path = "../libserialize" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index bcae7b262c6..bf5f7cde7eb 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -23,16 +23,9 @@
 #![feature(staged_api)]
 #![feature(range_contains)]
 #![feature(libc)]
-#![feature(unicode)]
 
-extern crate serialize;
 extern crate term;
-#[macro_use]
-extern crate log;
-#[macro_use]
 extern crate libc;
-extern crate std_unicode;
-extern crate serialize as rustc_serialize; // used by deriving
 extern crate syntax_pos;
 
 pub use emitter::ColorConfig;
diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml
index 8a38f36a5d1..e3ee7527545 100644
--- a/src/librustc_incremental/Cargo.toml
+++ b/src/librustc_incremental/Cargo.toml
@@ -16,4 +16,3 @@ serialize = { path = "../libserialize" }
 log = { path = "../liblog" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index e96d5977419..a866a15c4d2 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -30,11 +30,9 @@ extern crate rustc_data_structures;
 extern crate serialize as rustc_serialize;
 
 #[macro_use] extern crate log;
-#[macro_use] extern crate syntax;
+extern crate syntax;
 extern crate syntax_pos;
 
-extern crate rustc_i128;
-
 const ATTR_DIRTY: &'static str = "rustc_dirty";
 const ATTR_CLEAN: &'static str = "rustc_clean";
 const ATTR_DIRTY_METADATA: &'static str = "rustc_metadata_dirty";
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 60497fe171c..34bc57884ec 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -37,7 +37,6 @@
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 
-#[macro_use]
 extern crate syntax;
 #[macro_use]
 extern crate rustc;
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 7e26aa9a57b..9f49d02f86c 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -12,7 +12,6 @@ crate-type = ["dylib"]
 graphviz = { path = "../libgraphviz" }
 log = { path = "../liblog" }
 rustc = { path = "../librustc" }
-rustc_back = { path = "../librustc_back" }
 rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index e7493850aa7..e7764d58d75 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -31,7 +31,6 @@ extern crate graphviz as dot;
 #[macro_use]
 extern crate rustc;
 extern crate rustc_data_structures;
-extern crate rustc_back;
 #[macro_use]
 #[no_link]
 extern crate rustc_bitflags;
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 143c1efed5a..7a465f0ec42 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -27,7 +27,6 @@
 #![feature(staged_api)]
 #![feature(rustc_private)]
 
-extern crate core;
 #[macro_use]
 extern crate rustc;
 extern crate rustc_const_eval;
diff --git a/src/librustc_plugin/Cargo.toml b/src/librustc_plugin/Cargo.toml
index 48d4437358c..7f41d052761 100644
--- a/src/librustc_plugin/Cargo.toml
+++ b/src/librustc_plugin/Cargo.toml
@@ -10,10 +10,8 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-log = { path = "../liblog" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
-rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_metadata = { path = "../librustc_metadata" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs
index 8d4e61ad8e5..8aa680ca12d 100644
--- a/src/librustc_plugin/lib.rs
+++ b/src/librustc_plugin/lib.rs
@@ -63,9 +63,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 
-#[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
-#[macro_use] #[no_link] extern crate rustc_bitflags;
 
 extern crate rustc;
 extern crate rustc_back;
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 5e985687886..f74af416cde 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -249,6 +249,8 @@ impl<'a> Resolver<'a> {
                 // n.b. we don't need to look at the path option here, because cstore already did
                 let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
                 let module = self.get_extern_crate_root(crate_id);
+                self.populate_module_if_necessary(module);
+                let used = self.process_legacy_macro_imports(item, module, expansion);
                 let binding =
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
                 let directive = self.arenas.alloc_import_directive(ImportDirective {
@@ -260,11 +262,11 @@ impl<'a> Resolver<'a> {
                     module_path: Vec::new(),
                     vis: Cell::new(vis),
                     expansion: expansion,
+                    used: Cell::new(used),
                 });
+                self.potentially_unused_imports.push(directive);
                 let imported_binding = self.import(binding, directive);
                 self.define(parent, ident, TypeNS, imported_binding);
-                self.populate_module_if_necessary(module);
-                self.process_legacy_macro_imports(item, module, expansion);
             }
 
             ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
@@ -522,7 +524,6 @@ impl<'a> Resolver<'a> {
                            binding: &'a NameBinding<'a>,
                            span: Span,
                            allow_shadowing: bool) {
-        self.used_crates.insert(binding.def().def_id().krate);
         self.macro_names.insert(name);
         if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing {
             let msg = format!("`{}` is already in scope", name);
@@ -532,43 +533,61 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expansion: Mark) {
+    // This returns true if we should consider the underlying `extern crate` to be used.
+    fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expansion: Mark)
+                                    -> bool {
         let allow_shadowing = expansion == Mark::root();
         let legacy_imports = self.legacy_macro_imports(&item.attrs);
-        let cnum = module.def_id().unwrap().krate;
+        let mut used = legacy_imports != LegacyMacroImports::default();
 
         // `#[macro_use]` and `#[macro_reexport]` are only allowed at the crate root.
-        if self.current_module.parent.is_some() && legacy_imports != LegacyMacroImports::default() {
+        if self.current_module.parent.is_some() && used {
             span_err!(self.session, item.span, E0468,
                       "an `extern crate` loading macros must be at the crate root");
-        } else if !self.use_extern_macros &&
-                  self.session.cstore.dep_kind(cnum).macros_only() &&
-                  legacy_imports == LegacyMacroImports::default() {
+        } else if !self.use_extern_macros && !used &&
+                  self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() {
             let msg = "custom derive crates and `#[no_link]` crates have no effect without \
                        `#[macro_use]`";
             self.session.span_warn(item.span, msg);
-            self.used_crates.insert(cnum); // Avoid the normal unused extern crate warning
+            used = true; // Avoid the normal unused extern crate warning
         }
 
+        let (graph_root, arenas) = (self.graph_root, self.arenas);
+        let macro_use_directive = |span| arenas.alloc_import_directive(ImportDirective {
+            id: item.id,
+            parent: graph_root,
+            imported_module: Cell::new(Some(module)),
+            subclass: ImportDirectiveSubclass::MacroUse,
+            span: span,
+            module_path: Vec::new(),
+            vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))),
+            expansion: expansion,
+            used: Cell::new(false),
+        });
+
         if let Some(span) = legacy_imports.import_all {
+            let directive = macro_use_directive(span);
+            self.potentially_unused_imports.push(directive);
             module.for_each_child(|ident, ns, binding| if ns == MacroNS {
-                self.legacy_import_macro(ident.name, binding, span, allow_shadowing);
+                let imported_binding = self.import(binding, directive);
+                self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
             });
         } else {
             for (name, span) in legacy_imports.imports {
                 let ident = Ident::with_empty_ctxt(name);
                 let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
                 if let Ok(binding) = result {
-                    self.legacy_import_macro(name, binding, span, allow_shadowing);
+                    let directive = macro_use_directive(span);
+                    self.potentially_unused_imports.push(directive);
+                    let imported_binding = self.import(binding, directive);
+                    self.legacy_import_macro(name, imported_binding, span, allow_shadowing);
                 } else {
                     span_err!(self.session, span, E0469, "imported macro not found");
                 }
             }
         }
         for (name, span) in legacy_imports.reexports {
-            let krate = module.def_id().unwrap().krate;
-            self.used_crates.insert(krate);
-            self.session.cstore.export_macros(krate);
+            self.session.cstore.export_macros(module.def_id().unwrap().krate);
             let ident = Ident::with_empty_ctxt(name);
             let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
             if let Ok(binding) = result {
@@ -577,6 +596,7 @@ impl<'a> Resolver<'a> {
                 span_err!(self.session, span, E0470, "reexported macro not found");
             }
         }
+        used
     }
 
     // does this attribute list contain "macro_use"?
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 41391c65a12..d150ff1ff81 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -22,8 +22,9 @@
 use std::ops::{Deref, DerefMut};
 
 use Resolver;
+use resolve_imports::ImportDirectiveSubclass;
 
-use rustc::lint;
+use rustc::{lint, ty};
 use rustc::util::nodemap::NodeMap;
 use syntax::ast::{self, ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::visit::{self, Visitor};
@@ -86,16 +87,6 @@ impl<'a, 'b> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b> {
         }
 
         match item.node {
-            ast::ItemKind::ExternCrate(_) => {
-                if let Some(crate_num) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
-                    if !self.used_crates.contains(&crate_num) {
-                        self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
-                                              item.id,
-                                              item.span,
-                                              "unused extern crate".to_string());
-                    }
-                }
-            }
             ast::ItemKind::Use(ref p) => {
                 match p.node {
                     ViewPathSimple(..) => {
@@ -124,6 +115,25 @@ impl<'a, 'b> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b> {
 }
 
 pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
+    for directive in resolver.potentially_unused_imports.iter() {
+        match directive.subclass {
+            _ if directive.used.get() ||
+                 directive.vis.get() == ty::Visibility::Public ||
+                 directive.span.source_equal(&DUMMY_SP) => {}
+            ImportDirectiveSubclass::ExternCrate => {
+                let lint = lint::builtin::UNUSED_EXTERN_CRATES;
+                let msg = "unused extern crate".to_string();
+                resolver.session.add_lint(lint, directive.id, directive.span, msg);
+            }
+            ImportDirectiveSubclass::MacroUse => {
+                let lint = lint::builtin::UNUSED_IMPORTS;
+                let msg = "unused `#[macro_use]` import".to_string();
+                resolver.session.add_lint(lint, directive.id, directive.span, msg);
+            }
+            _ => {}
+        }
+    }
+
     let mut visitor = UnusedImportCheckVisitor {
         resolver: resolver,
         unused_imports: NodeMap(),
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 971b91ea313..8a206664a7d 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1099,7 +1099,6 @@ pub struct Resolver<'a> {
     pub glob_map: GlobMap,
 
     used_imports: FxHashSet<(NodeId, Namespace)>,
-    used_crates: FxHashSet<CrateNum>,
     pub maybe_unused_trait_imports: NodeSet,
 
     privacy_errors: Vec<PrivacyError<'a>>,
@@ -1130,6 +1129,8 @@ pub struct Resolver<'a> {
 
     // A set of procedural macros imported by `#[macro_use]` that have already been warned about
     warned_proc_macros: FxHashSet<Name>,
+
+    potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
 }
 
 pub struct ResolverArenas<'a> {
@@ -1279,7 +1280,6 @@ impl<'a> Resolver<'a> {
             glob_map: NodeMap(),
 
             used_imports: FxHashSet(),
-            used_crates: FxHashSet(),
             maybe_unused_trait_imports: NodeSet(),
 
             privacy_errors: Vec::new(),
@@ -1309,6 +1309,7 @@ impl<'a> Resolver<'a> {
             whitelisted_legacy_custom_derives: Vec::new(),
             proc_macro_enabled: features.proc_macro,
             warned_proc_macros: FxHashSet(),
+            potentially_unused_imports: Vec::new(),
         }
     }
 
@@ -1354,15 +1355,11 @@ impl<'a> Resolver<'a> {
 
     fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
                   -> bool /* true if an error was reported */ {
-        // track extern crates for unused_extern_crate lint
-        if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleData::def_id) {
-            self.used_crates.insert(krate);
-        }
-
         match binding.kind {
             NameBindingKind::Import { directive, binding, ref used, legacy_self_import }
                     if !used.get() => {
                 used.set(true);
+                directive.used.set(true);
                 if legacy_self_import {
                     self.warn_legacy_self_import(directive);
                     return false;
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 9b7d6f33a7f..682b3ff834f 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -341,12 +341,15 @@ impl<'a> Resolver<'a> {
             };
         }
 
-        let binding = match binding {
-            Some(binding) => MacroBinding::Legacy(binding),
-            None => match self.builtin_macros.get(&name).cloned() {
-                Some(binding) => MacroBinding::Modern(binding),
-                None => return None,
-            },
+        let binding = if let Some(binding) = binding {
+            MacroBinding::Legacy(binding)
+        } else if let Some(binding) = self.builtin_macros.get(&name).cloned() {
+            if !self.use_extern_macros {
+                self.record_use(Ident::with_empty_ctxt(name), MacroNS, binding, DUMMY_SP);
+            }
+            MacroBinding::Modern(binding)
+        } else {
+            return None;
         };
 
         if !self.use_extern_macros {
@@ -378,6 +381,7 @@ impl<'a> Resolver<'a> {
             let (legacy_resolution, resolution) = match (legacy_resolution, resolution) {
                 (Some(legacy_resolution), Ok(resolution)) => (legacy_resolution, resolution),
                 (Some(MacroBinding::Modern(binding)), Err(_)) => {
+                    self.record_use(ident, MacroNS, binding, span);
                     self.err_if_macro_use_proc_macro(ident.name, span, binding);
                     continue
                 },
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 65e599ac6c7..65cdeb9253d 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -49,6 +49,7 @@ pub enum ImportDirectiveSubclass<'a> {
         // n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
     },
     ExternCrate,
+    MacroUse,
 }
 
 /// One import directive.
@@ -62,6 +63,7 @@ pub struct ImportDirective<'a> {
     pub span: Span,
     pub vis: Cell<ty::Visibility>,
     pub expansion: Mark,
+    pub used: Cell<bool>,
 }
 
 impl<'a> ImportDirective<'a> {
@@ -257,6 +259,7 @@ impl<'a> Resolver<'a> {
             id: id,
             vis: Cell::new(vis),
             expansion: expansion,
+            used: Cell::new(false),
         });
 
         self.indeterminate_imports.push(directive);
@@ -833,5 +836,6 @@ fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> St
         SingleImport { source, .. } => source.to_string(),
         GlobImport { .. } => "*".to_string(),
         ExternCrate => "<extern crate>".to_string(),
+        MacroUse => "#[macro_use]".to_string(),
     }
 }
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index 93e2e472b75..36d2ba4f367 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -10,9 +10,7 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
-arena = { path = "../libarena" }
 flate = { path = "../libflate" }
-graphviz = { path = "../libgraphviz" }
 log = { path = "../liblog" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
@@ -25,6 +23,5 @@ rustc_incremental = { path = "../librustc_incremental" }
 rustc_llvm = { path = "../librustc_llvm" }
 rustc_i128 = { path = "../librustc_i128" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
-serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index d8c0bde963e..659dbb441ee 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -40,10 +40,7 @@
 
 use rustc::dep_graph::WorkProduct;
 
-extern crate arena;
 extern crate flate;
-extern crate getopts;
-extern crate graphviz;
 extern crate libc;
 #[macro_use] extern crate rustc;
 extern crate rustc_back;
@@ -51,7 +48,6 @@ extern crate rustc_data_structures;
 extern crate rustc_incremental;
 pub extern crate rustc_llvm as llvm;
 extern crate rustc_platform_intrinsics as intrinsics;
-extern crate serialize;
 extern crate rustc_const_math;
 extern crate rustc_const_eval;
 #[macro_use]
diff --git a/src/libserialize/Cargo.toml b/src/libserialize/Cargo.toml
index 3213b4e4208..47403b45981 100644
--- a/src/libserialize/Cargo.toml
+++ b/src/libserialize/Cargo.toml
@@ -9,5 +9,4 @@ path = "lib.rs"
 crate-type = ["dylib", "rlib"]
 
 [dependencies]
-log = { path = "../liblog" }
 rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index cfa09361cce..2cfc3924c03 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -31,17 +31,10 @@ Core encoding and decoding interfaces.
 #![feature(collections)]
 #![feature(core_intrinsics)]
 #![feature(enumset)]
-#![feature(rustc_private)]
 #![feature(specialization)]
 #![feature(staged_api)]
-#![feature(unicode)]
 #![cfg_attr(test, feature(test))]
 
-// test harness access
-#[cfg(test)] extern crate test;
-#[macro_use] extern crate log;
-
-extern crate std_unicode;
 extern crate collections;
 
 extern crate rustc_i128;
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 00bf7445077..f3c5a49bcf8 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -26,7 +26,6 @@
 
 #![feature(associated_consts)]
 #![feature(const_fn)]
-#![feature(libc)]
 #![feature(optin_builtin_traits)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
@@ -35,10 +34,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(specialization)]
 
-extern crate core;
 extern crate serialize;
-extern crate term;
-extern crate libc;
 #[macro_use] extern crate log;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
 extern crate std_unicode;
diff --git a/src/test/compile-fail/imports/unused-macro-use.rs b/src/test/compile-fail/imports/unused-macro-use.rs
new file mode 100644
index 00000000000..365521970cd
--- /dev/null
+++ b/src/test/compile-fail/imports/unused-macro-use.rs
@@ -0,0 +1,21 @@
+// 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.
+
+#![deny(unused)]
+
+#[macro_use] //~ ERROR unused `#[macro_use]` import
+extern crate core;
+
+#[macro_use(
+    panic //~ ERROR unused `#[macro_use]` import
+)]
+extern crate core as core_2;
+
+fn main() {}
diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs
index 52cb84f662d..40671353f8a 100644
--- a/src/test/compile-fail/lint-unused-extern-crate.rs
+++ b/src/test/compile-fail/lint-unused-extern-crate.rs
@@ -26,13 +26,16 @@ extern crate rand; // no error, the use marks it as used
 
 extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used
 
-#[macro_use] extern crate core; // no error, the `#[macro_use]` marks it as used
-
 #[allow(unused_imports)]
 use rand::isaac::IsaacRng;
 
 use other::*;
 
+mod foo {
+    // Test that this is unused even though an earler `extern crate rand` is used.
+    extern crate rand; //~ ERROR unused extern crate
+}
+
 fn main() {
     let x: collecs::vec::Vec<usize> = Vec::new();
     let y = foo();
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index 8a891d624f4..83fd766c547 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -25,7 +25,7 @@ const TEST_REPOS: &'static [Test] = &[
     Test {
         name: "cargo",
         repo: "https://github.com/rust-lang/cargo",
-        sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
+        sha: "2324c2bbaf7fc6ea9cbdd77c034ef1af769cb617",
         lock: None,
     },
     Test {