diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index f06062fa4ac83..d08519d3703e0 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1508,3 +1508,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 4f6d23dce6dbb..39f550a4b459a 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_idioms", 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 0000000000000..9d678d91578bc --- /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 or the MIT license +// , 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 0000000000000..7718808be58ba --- /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 +