Skip to content

Commit

Permalink
Auto merge of #50260 - Manishearth:no-extern-crate, r=nikomatsakis
Browse files Browse the repository at this point in the history
idiom lints for removing `extern crate`

Based off of #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 #48719
  • Loading branch information
bors committed May 8, 2018
2 parents 715d6a9 + 01791de commit 0da1a69
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 1 deletion.
63 changes: 63 additions & 0 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
4 changes: 3 additions & 1 deletion src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
TypeLimits,
MissingDoc,
MissingDebugImplementations,
ExternCrate,
);

add_lint_group!(sess,
Expand Down Expand Up @@ -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:
//
Expand Down
55 changes: 55 additions & 0 deletions src/test/ui-fulldeps/unnecessary-extern-crate.rs
Original file line number Diff line number Diff line change
@@ -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() {}
68 changes: 68 additions & 0 deletions src/test/ui-fulldeps/unnecessary-extern-crate.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 0da1a69

Please sign in to comment.