about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-05-08 01:37:52 +0000
committerbors <bors@rust-lang.org>2018-05-08 01:37:52 +0000
commit0da1a69003bd37ef0ee2cde2eb66a9e2752fc6c2 (patch)
treeedd8b535e989e1c8e723a41dfb26ecdc80adb828
parent715d6a98aa4908dfb85b55f97e51af330d0baf7f (diff)
parent01791dee8a6c93bdbc9e3c9369b6b5f0ee35e5c8 (diff)
downloadrust-0da1a69003bd37ef0ee2cde2eb66a9e2752fc6c2.tar.gz
rust-0da1a69003bd37ef0ee2cde2eb66a9e2752fc6c2.zip
Auto merge of #50260 - Manishearth:no-extern-crate, r=nikomatsakis
idiom lints for removing `extern crate`

Based off of https://github.com/rust-lang/rust/pull/49789

This contains two lints:

 - One that suggests replacing pub extern crates with pub use, and removing non-pub extern crates entirely
 - One that suggests rewriting `use modulename::...::cratename::foo` as `cratename::foo`

The latter is a bit tricky to emit suggestions for; for one this involves splicing spans (never a good idea), and it also won't be able to correctly
handle `use module::{cratename, foo}` and use-trees. I'm not sure how to proceed here. Currently it doesn't suggest anything at all.

Perhaps we can go the other way and suggest removal of all extern crates _except_ those used through modules (stash node ids somewhere) and suggest replacing those with `<visibility> use`?

r? @nikomatsakis

fixes https://github.com/rust-lang/rust/issues/48719
-rw-r--r--src/librustc_lint/builtin.rs63
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/test/ui-fulldeps/unnecessary-extern-crate.rs55
-rw-r--r--src/test/ui-fulldeps/unnecessary-extern-crate.stderr68
4 files changed, 189 insertions, 1 deletions
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 817abe2ceeb..7ae13c803dd 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1520,3 +1520,66 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
         }
     }
 }
+
+declare_lint! {
+    pub UNNECESSARY_EXTERN_CRATE,
+    Allow,
+    "suggest removing `extern crate` for the 2018 edition"
+}
+
+pub struct ExternCrate(/* depth */ u32);
+
+impl ExternCrate {
+    pub fn new() -> Self {
+        ExternCrate(0)
+    }
+}
+
+impl LintPass for ExternCrate {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNNECESSARY_EXTERN_CRATE)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExternCrate {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        if let hir::ItemExternCrate(ref orig) =  it.node {
+            if it.attrs.iter().any(|a| a.check_name("macro_use")) {
+                return
+            }
+            let mut err = cx.struct_span_lint(UNNECESSARY_EXTERN_CRATE,
+                it.span, "`extern crate` is unnecessary in the new edition");
+            if it.vis == hir::Visibility::Public || self.0 > 1 || orig.is_some() {
+                let pub_ = if it.vis == hir::Visibility::Public {
+                    "pub "
+                } else {
+                    ""
+                };
+
+                let help = format!("use `{}use`", pub_);
+
+                if let Some(orig) = orig {
+                    err.span_suggestion(it.span, &help,
+                        format!("{}use {} as {}", pub_, orig, it.name));
+                } else {
+                    err.span_suggestion(it.span, &help,
+                        format!("{}use {}", pub_, it.name));
+                }
+            } else {
+                err.span_suggestion(it.span, "remove it", "".into());
+            }
+
+            err.emit();
+        }
+    }
+
+    fn check_mod(&mut self, _: &LateContext, _: &hir::Mod,
+                 _: Span, _: ast::NodeId) {
+        self.0 += 1;
+    }
+
+    fn check_mod_post(&mut self, _: &LateContext, _: &hir::Mod,
+                      _: Span, _: ast::NodeId) {
+        self.0 += 1;
+    }
+}
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 074fa914f37..4403e1e3358 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -143,6 +143,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                           TypeLimits,
                           MissingDoc,
                           MissingDebugImplementations,
+                          ExternCrate,
                           );
 
     add_lint_group!(sess,
@@ -180,7 +181,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     add_lint_group!(sess,
                     "rust_2018_migration",
                     BARE_TRAIT_OBJECT,
-                    UNREACHABLE_PUB);
+                    UNREACHABLE_PUB,
+                    UNNECESSARY_EXTERN_CRATE);
 
     // Guidelines for creating a future incompatibility lint:
     //
diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.rs b/src/test/ui-fulldeps/unnecessary-extern-crate.rs
new file mode 100644
index 00000000000..9d678d91578
--- /dev/null
+++ b/src/test/ui-fulldeps/unnecessary-extern-crate.rs
@@ -0,0 +1,55 @@
+// Copyright 2015 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(unnecessary_extern_crate)]
+#![feature(alloc, test, libc)]
+
+extern crate alloc;
+//~^ ERROR `extern crate` is unnecessary in the new edition
+//~| HELP remove
+extern crate alloc as x;
+//~^ ERROR `extern crate` is unnecessary in the new edition
+//~| HELP use `use`
+
+#[macro_use]
+extern crate test;
+pub extern crate test as y;
+//~^ ERROR `extern crate` is unnecessary in the new edition
+//~| HELP use `pub use`
+pub extern crate libc;
+//~^ ERROR `extern crate` is unnecessary in the new edition
+//~| HELP use `pub use`
+
+
+mod foo {
+    extern crate alloc;
+    //~^ ERROR `extern crate` is unnecessary in the new edition
+    //~| HELP use `use`
+    extern crate alloc as x;
+    //~^ ERROR `extern crate` is unnecessary in the new edition
+    //~| HELP use `use`
+    pub extern crate test;
+    //~^ ERROR `extern crate` is unnecessary in the new edition
+    //~| HELP use `pub use`
+    pub extern crate test as y;
+    //~^ ERROR `extern crate` is unnecessary in the new edition
+    //~| HELP use `pub use`
+    mod bar {
+        extern crate alloc;
+        //~^ ERROR `extern crate` is unnecessary in the new edition
+        //~| HELP use `use`
+        extern crate alloc as x;
+        //~^ ERROR `extern crate` is unnecessary in the new edition
+        //~| HELP use `use`
+    }
+}
+
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr
new file mode 100644
index 00000000000..7718808be58
--- /dev/null
+++ b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr
@@ -0,0 +1,68 @@
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:14:1
+   |
+LL | extern crate alloc;
+   | ^^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/unnecessary-extern-crate.rs:11:9
+   |
+LL | #![deny(unnecessary_extern_crate)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:17:1
+   |
+LL | extern crate alloc as x;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:23:1
+   |
+LL | pub extern crate test as y;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:26:1
+   |
+LL | pub extern crate libc;
+   | ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use libc`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:32:5
+   |
+LL |     extern crate alloc;
+   |     ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:35:5
+   |
+LL |     extern crate alloc as x;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:38:5
+   |
+LL |     pub extern crate test;
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:41:5
+   |
+LL |     pub extern crate test as y;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:45:9
+   |
+LL |         extern crate alloc;
+   |         ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:48:9
+   |
+LL |         extern crate alloc as x;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x`
+
+error: aborting due to 10 previous errors
+