Auto merge of #51015 - nikomatsakis:issue-50672-remove-extern-crate-idiom, r=alexcrichton

merge unused-extern-crate and unnecessary-extern-crate lints

Extend the `unused_extern_crates` lint to offer a suggestion to remove the extern crate and remove the `unnecessary_extern_crate` lint.

Still a few minor issues to fix:
- [x] this *does* now leave a blank line... (defer to https://github.com/rust-lang/rust/issues/51176)
  - idea: extend the span to be replaced by 1 character if the next character is a `\n`
- [x] what about macros? do we need to watch out for that? (defer to https://github.com/rust-lang/rust/issues/48704)
- [x] also it doesn't work for `extern crate foo; fn main() { foo::bar(); }`
  - this is subtle: the `foo` might be shadowing a glob import too, can't always remove
  - defer to https://github.com/rust-lang/rust/issues/51177
- [x] we also don't do the `pub use` rewrite thang (https://github.com/rust-lang/rust/issues/51013)

Spun off from https://github.com/rust-lang/rust/pull/51010

Fixes #50672

r? @alexcrichton
This commit is contained in:
bors 2018-06-02 11:14:14 +00:00
commit 1b3d737716
19 changed files with 429 additions and 210 deletions

View File

@ -2433,7 +2433,7 @@ impl<'a> LoweringContext<'a> {
self.with_hir_id_owner(new_id, |this| {
let vis = match vis {
hir::Visibility::Public => hir::Visibility::Public,
hir::Visibility::Crate => hir::Visibility::Crate,
hir::Visibility::Crate(sugar) => hir::Visibility::Crate(sugar),
hir::Visibility::Inherited => hir::Visibility::Inherited,
hir::Visibility::Restricted { ref path, id: _ } => {
hir::Visibility::Restricted {
@ -3704,7 +3704,7 @@ impl<'a> LoweringContext<'a> {
) -> hir::Visibility {
match v.node {
VisibilityKind::Public => hir::Public,
VisibilityKind::Crate(..) => hir::Visibility::Crate,
VisibilityKind::Crate(sugar) => hir::Visibility::Crate(sugar),
VisibilityKind::Restricted { ref path, id, .. } => hir::Visibility::Restricted {
path: P(self.lower_path(id, path, ParamMode::Explicit)),
id: if let Some(owner) = explicit_owner {

View File

@ -463,7 +463,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
fn visit_vis(&mut self, visibility: &'hir Visibility) {
match *visibility {
Visibility::Public |
Visibility::Crate |
Visibility::Crate(_) |
Visibility::Inherited => {}
Visibility::Restricted { id, .. } => {
self.insert(id, NodeVisibility(visibility));

View File

@ -35,7 +35,7 @@ use mir::mono::Linkage;
use syntax_pos::{Span, DUMMY_SP};
use syntax::codemap::{self, Spanned};
use rustc_target::spec::abi::Abi;
use syntax::ast::{self, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
use syntax::attr::InlineAttr;
use syntax::ext::hygiene::SyntaxContext;
@ -1953,7 +1953,7 @@ pub struct PolyTraitRef {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Visibility {
Public,
Crate,
Crate(CrateSugar),
Restricted { path: P<Path>, id: NodeId },
Inherited,
}
@ -1964,7 +1964,7 @@ impl Visibility {
match self {
&Public |
&Inherited => false,
&Crate |
&Crate(_) |
&Restricted { .. } => true,
}
}

View File

@ -801,15 +801,25 @@ impl<'a> State<'a> {
pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
match *vis {
hir::Public => self.word_nbsp("pub"),
hir::Visibility::Crate => self.word_nbsp("pub(crate)"),
hir::Public => self.word_nbsp("pub")?,
hir::Visibility::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate")?,
hir::Visibility::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)")?,
hir::Visibility::Restricted { ref path, .. } => {
self.s.word("pub(")?;
self.print_path(path, false)?;
self.word_nbsp(")")
if path.segments.len() == 1 && path.segments[0].name == keywords::Super.name() {
// Special case: `super` can print like `pub(super)`.
self.s.word("super")?;
} else {
// Everything else requires `in` at present.
self.word_nbsp("in")?;
self.print_path(path, false)?;
}
self.word_nbsp(")")?;
}
hir::Inherited => Ok(()),
hir::Inherited => ()
}
Ok(())
}
pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {

View File

@ -751,6 +751,11 @@ impl_stable_hash_for!(enum hir::ImplItemKind {
Type(t)
});
impl_stable_hash_for!(enum ::syntax::ast::CrateSugar {
JustCrate,
PubCrate,
});
impl<'a> HashStable<StableHashingContext<'a>> for hir::Visibility {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
@ -758,10 +763,12 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Visibility {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
hir::Visibility::Public |
hir::Visibility::Crate |
hir::Visibility::Inherited => {
// No fields to hash.
}
hir::Visibility::Crate(sugar) => {
sugar.hash_stable(hcx, hasher);
}
hir::Visibility::Restricted { ref path, id } => {
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
id.hash_stable(hcx, hasher);

View File

@ -270,7 +270,7 @@ impl Visibility {
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
match *visibility {
hir::Public => Visibility::Public,
hir::Visibility::Crate => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
hir::Visibility::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
hir::Visibility::Restricted { ref path, .. } => match path.def {
// If there is no resolution, `resolve` will have already reported an error, so
// assume that the visibility is public to avoid reporting more privacy errors.

View File

@ -1548,72 +1548,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
}
}
declare_lint! {
pub UNNECESSARY_EXTERN_CRATES,
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_CRATES)
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExternCrate {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
if !cx.tcx.features().extern_absolute_paths {
return
}
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_CRATES,
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;
}
}
/// Lint for trait and lifetime bounds that don't depend on type parameters
/// which either do nothing, or stop the item from being used.
pub struct TrivialConstraints;

View File

@ -145,7 +145,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
TypeLimits,
MissingDoc,
MissingDebugImplementations,
ExternCrate,
);
add_lint_group!(sess,
@ -185,7 +184,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
"rust_2018_idioms",
BARE_TRAIT_OBJECTS,
UNREACHABLE_PUB,
UNNECESSARY_EXTERN_CRATES);
UNUSED_EXTERN_CRATES);
// Guidelines for creating a future incompatibility lint:
//

View File

@ -14,11 +14,46 @@ use rustc::ty::TyCtxt;
use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::print::visibility_qualified;
use rustc::hir;
use rustc::util::nodemap::DefIdSet;
use rustc_data_structures::fx::FxHashMap;
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let mut used_trait_imports = DefIdSet();
for &body_id in tcx.hir.krate().bodies.keys() {
let item_def_id = tcx.hir.body_owner_def_id(body_id);
let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
used_trait_imports.extend(imports.iter());
}
let mut visitor = CheckVisitor { tcx, used_trait_imports };
tcx.hir.krate().visit_all_item_likes(&mut visitor);
unused_crates_lint(tcx);
}
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if item.vis == hir::Public || item.span == DUMMY_SP {
return;
}
if let hir::ItemUse(ref path, _) = item.node {
self.check_import(item.id, path.span);
}
}
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
}
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
}
}
struct CheckVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
used_trait_imports: DefIdSet,
@ -45,13 +80,131 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if item.vis == hir::Public || item.span == DUMMY_SP {
return;
fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
// Collect first the crates that are completely unused. These we
// can always suggest removing (no matter which edition we are
// in).
let unused_extern_crates: FxHashMap<DefId, Span> =
tcx.maybe_unused_extern_crates(LOCAL_CRATE)
.iter()
.filter(|&&(def_id, _)| {
// The `def_id` here actually was calculated during resolution (at least
// at the time of this writing) and is being shipped to us via a side
// channel of the tcx. There may have been extra expansion phases,
// however, which ended up removing the `def_id` *after* expansion such
// as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey)
//
// As a result we need to verify that `def_id` is indeed still valid for
// our AST and actually present in the HIR map. If it's not there then
// there's safely nothing to warn about, and otherwise we carry on with
// our execution.
//
// Note that if we carry through to the `extern_mod_stmt_cnum` query
// below it'll cause a panic because `def_id` is actually bogus at this
// point in time otherwise.
if let Some(id) = tcx.hir.as_local_node_id(def_id) {
if tcx.hir.find(id).is_none() {
return false;
}
}
true
})
.filter(|&&(def_id, _)| {
let cnum = tcx.extern_mod_stmt_cnum(def_id).unwrap();
!tcx.is_compiler_builtins(cnum)
&& !tcx.is_panic_runtime(cnum)
&& !tcx.has_global_allocator(cnum)
})
.cloned()
.collect();
// Collect all the extern crates (in a reliable order).
let mut crates_to_lint = vec![];
tcx.hir.krate().visit_all_item_likes(&mut CollectExternCrateVisitor {
tcx,
crates_to_lint: &mut crates_to_lint,
});
for extern_crate in &crates_to_lint {
assert!(extern_crate.def_id.is_local());
// If the crate is fully unused, we suggest removing it altogether.
// We do this in any edition.
if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
let id = tcx.hir.hir_to_node_id(hir_id);
let msg = "unused extern crate";
tcx.struct_span_lint_node(lint, id, span, msg)
.span_suggestion_short(span, "remove it", "".to_string())
.emit();
continue;
}
if let hir::ItemUse(ref path, _) = item.node {
self.check_import(item.id, path.span);
// If we are not in Rust 2018 edition, then we don't make any further
// suggestions.
if !tcx.sess.rust_2018() {
continue;
}
// If the extern crate has any attributes, they may have funky
// semantics we can't faithfully represent using `use` (most
// notably `#[macro_use]`). Ignore it.
if !tcx.get_attrs(extern_crate.def_id).is_empty() {
continue;
}
// Otherwise, we can convert it into a `use` of some kind.
let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
let id = tcx.hir.hir_to_node_id(hir_id);
let item = tcx.hir.expect_item(id);
let msg = "`extern crate` is not idiomatic in the new edition";
let help = format!(
"convert it to a `{}`",
visibility_qualified(&item.vis, "use")
);
let base_replacement = match extern_crate.orig_name {
Some(orig_name) => format!("use {} as {};", orig_name, item.name),
None => format!("use {};", item.name),
};
let replacement = visibility_qualified(&item.vis, &base_replacement);
tcx.struct_span_lint_node(lint, id, extern_crate.span, msg)
.span_suggestion_short(extern_crate.span, &help, replacement)
.emit();
}
}
struct CollectExternCrateVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
crates_to_lint: &'a mut Vec<ExternCrateToLint>,
}
struct ExternCrateToLint {
/// def-id of the extern crate
def_id: DefId,
/// span from the item
span: Span,
/// if `Some`, then this is renamed (`extern crate orig_name as
/// crate_name`), and -- perhaps surprisingly -- this stores the
/// *original* name (`item.name` will contain the new name)
orig_name: Option<ast::Name>,
}
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if let hir::ItemExternCrate(orig_name) = item.node {
let extern_crate_def_id = self.tcx.hir.local_def_id(item.id);
self.crates_to_lint.push(
ExternCrateToLint {
def_id: extern_crate_def_id,
span: item.span,
orig_name,
}
);
}
}
@ -62,53 +215,3 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
}
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let mut used_trait_imports = DefIdSet();
for &body_id in tcx.hir.krate().bodies.keys() {
let item_def_id = tcx.hir.body_owner_def_id(body_id);
let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
used_trait_imports.extend(imports.iter());
}
let mut visitor = CheckVisitor { tcx, used_trait_imports };
tcx.hir.krate().visit_all_item_likes(&mut visitor);
for &(def_id, span) in tcx.maybe_unused_extern_crates(LOCAL_CRATE).iter() {
// The `def_id` here actually was calculated during resolution (at least
// at the time of this writing) and is being shipped to us via a side
// channel of the tcx. There may have been extra expansion phases,
// however, which ended up removing the `def_id` *after* expansion such
// as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey)
//
// As a result we need to verify that `def_id` is indeed still valid for
// our AST and actually present in the HIR map. If it's not there then
// there's safely nothing to warn about, and otherwise we carry on with
// our execution.
//
// Note that if we carry through to the `extern_mod_stmt_cnum` query
// below it'll cause a panic because `def_id` is actually bogus at this
// point in time otherwise.
if let Some(id) = tcx.hir.as_local_node_id(def_id) {
if tcx.hir.find(id).is_none() {
continue
}
}
let cnum = tcx.extern_mod_stmt_cnum(def_id).unwrap();
if tcx.is_compiler_builtins(cnum) {
continue
}
if tcx.is_panic_runtime(cnum) {
continue
}
if tcx.has_global_allocator(cnum) {
continue
}
assert_eq!(def_id.krate, LOCAL_CRATE);
let hir_id = tcx.hir.definitions().def_index_to_hir_id(def_id.index);
let id = tcx.hir.hir_to_node_id(hir_id);
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
let msg = "unused extern crate";
tcx.lint_node(lint, id, span, msg);
}
}

View File

@ -3030,7 +3030,7 @@ impl Clean<Option<Visibility>> for hir::Visibility {
Some(match *self {
hir::Visibility::Public => Visibility::Public,
hir::Visibility::Inherited => Visibility::Inherited,
hir::Visibility::Crate => Visibility::Crate,
hir::Visibility::Crate(_) => Visibility::Crate,
hir::Visibility::Restricted { ref path, .. } => {
let path = path.clean(cx);
let did = register_def(cx, path.def);

View File

@ -12,8 +12,9 @@
// compile-flags: --edition 2015
// compile-pass
#![deny(rust_2018_idioms)]
#![warn(rust_2018_idioms)]
extern crate edition_extern_crate_allowed;
//~^ WARNING unused extern crate
fn main() {}

View File

@ -10,48 +10,90 @@
// compile-flags: --edition 2018
#![deny(unnecessary_extern_crates)]
#![deny(unused_extern_crates)]
#![feature(alloc, test, libc)]
extern crate alloc;
//~^ ERROR `extern crate` is unnecessary in the new edition
//~^ ERROR unused extern crate
//~| HELP remove
extern crate alloc as x;
//~^ ERROR `extern crate` is unnecessary in the new edition
//~| HELP use `use`
//~^ ERROR unused extern crate
//~| HELP remove
#[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`
pub extern crate test as y;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub use`
pub extern crate libc;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub use`
pub(crate) extern crate libc as a;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub(crate) use`
crate extern crate libc as b;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `crate use`
mod foo {
pub(in crate::foo) extern crate libc as c;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub(in crate::foo) use`
pub(super) extern crate libc as d;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub(super) use`
extern crate alloc;
//~^ ERROR `extern crate` is unnecessary in the new edition
//~| HELP use `use`
//~^ ERROR unused extern crate
//~| HELP remove
extern crate alloc as x;
//~^ ERROR `extern crate` is unnecessary in the new edition
//~| HELP use `use`
//~^ ERROR unused extern crate
//~| HELP remove
pub extern crate test;
//~^ ERROR `extern crate` is unnecessary in the new edition
//~| HELP use `pub use`
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it
pub extern crate test as y;
//~^ ERROR `extern crate` is unnecessary in the new edition
//~| HELP use `pub use`
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it
mod bar {
extern crate alloc;
//~^ ERROR `extern crate` is unnecessary in the new edition
//~| HELP use `use`
//~^ ERROR unused extern crate
//~| HELP remove
extern crate alloc as x;
//~^ ERROR `extern crate` is unnecessary in the new edition
//~| HELP use `use`
//~^ ERROR unused extern crate
//~| HELP remove
pub(in crate::foo::bar) extern crate libc as e;
//~^ ERROR `extern crate` is not idiomatic in the new edition
//~| HELP convert it to a `pub(in crate::foo::bar) use`
fn dummy() {
unsafe {
e::getpid();
}
}
}
fn dummy() {
unsafe {
c::getpid();
d::getpid();
}
}
}
fn main() {}
fn main() {
unsafe { a::getpid(); }
unsafe { b::getpid(); }
}

View File

@ -1,4 +1,4 @@
error: `extern crate` is unnecessary in the new edition
error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:16:1
|
LL | extern crate alloc;
@ -7,62 +7,92 @@ LL | extern crate alloc;
note: lint level defined here
--> $DIR/unnecessary-extern-crate.rs:13:9
|
LL | #![deny(unnecessary_extern_crates)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
LL | #![deny(unused_extern_crates)]
| ^^^^^^^^^^^^^^^^^^^^
error: `extern crate` is unnecessary in the new edition
error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:19:1
|
LL | extern crate alloc as x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
error: `extern crate` is unnecessary in the new edition
--> $DIR/unnecessary-extern-crate.rs:25:1
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:26:1
|
LL | pub extern crate test as y;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y;`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
error: `extern crate` is unnecessary in the new edition
--> $DIR/unnecessary-extern-crate.rs:28:1
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:30:1
|
LL | pub extern crate libc;
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use libc;`
| ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
error: `extern crate` is unnecessary in the new edition
--> $DIR/unnecessary-extern-crate.rs:34:5
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:34:1
|
LL | extern crate alloc;
| ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc;`
LL | pub(crate) extern crate libc as a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(crate) use`
error: `extern crate` is unnecessary in the new edition
--> $DIR/unnecessary-extern-crate.rs:37:5
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:38:1
|
LL | extern crate alloc as x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
LL | crate extern crate libc as b;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `crate use`
error: `extern crate` is unnecessary in the new edition
--> $DIR/unnecessary-extern-crate.rs:40:5
|
LL | pub extern crate test;
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test;`
error: `extern crate` is unnecessary in the new edition
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:43:5
|
LL | pub extern crate test as y;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y;`
LL | pub(in crate::foo) extern crate libc as c;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo) use`
error: `extern crate` is unnecessary in the new edition
--> $DIR/unnecessary-extern-crate.rs:47:9
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:47:5
|
LL | pub(super) extern crate libc as d;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(super) use`
error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:51:5
|
LL | extern crate alloc;
| ^^^^^^^^^^^^^^^^^^^ help: remove it
error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:55:5
|
LL | extern crate alloc as x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:59:5
|
LL | pub extern crate test;
| ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:63:5
|
LL | pub extern crate test as y;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:68:9
|
LL | extern crate alloc;
| ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc;`
| ^^^^^^^^^^^^^^^^^^^ help: remove it
error: `extern crate` is unnecessary in the new edition
--> $DIR/unnecessary-extern-crate.rs:50:9
error: unused extern crate
--> $DIR/unnecessary-extern-crate.rs:72:9
|
LL | extern crate alloc as x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
error: aborting due to 10 previous errors
error: `extern crate` is not idiomatic in the new edition
--> $DIR/unnecessary-extern-crate.rs:76:9
|
LL | pub(in crate::foo::bar) extern crate libc as e;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo::bar) use`
error: aborting due to 15 previous errors

View File

@ -20,7 +20,7 @@ warning: unused extern crate
--> $DIR/basic.rs:33:5
|
LL | extern crate core as _; //~ WARN unused extern crate
| ^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
|
note: lint level defined here
--> $DIR/basic.rs:14:25

View File

@ -0,0 +1,36 @@
// Copyright 2018 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:edition-lint-paths.rs
// run-rustfix
// compile-flags:--edition 2018
// The "normal case". Ideally we would remove the `extern crate` here,
// but we don't.
#![feature(rust_2018_preview)]
#![deny(rust_2018_idioms)]
#![allow(dead_code)]
//~^ ERROR unused extern crate
use edition_lint_paths as bar;
//~^ ERROR `extern crate` is not idiomatic in the new edition
fn main() {
// This is not considered to *use* the `extern crate` in Rust 2018:
use edition_lint_paths::foo;
foo();
// But this should be a use of the (renamed) crate:
crate::bar::foo();
}

View File

@ -0,0 +1,36 @@
// Copyright 2018 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:edition-lint-paths.rs
// run-rustfix
// compile-flags:--edition 2018
// The "normal case". Ideally we would remove the `extern crate` here,
// but we don't.
#![feature(rust_2018_preview)]
#![deny(rust_2018_idioms)]
#![allow(dead_code)]
extern crate edition_lint_paths;
//~^ ERROR unused extern crate
extern crate edition_lint_paths as bar;
//~^ ERROR `extern crate` is not idiomatic in the new edition
fn main() {
// This is not considered to *use* the `extern crate` in Rust 2018:
use edition_lint_paths::foo;
foo();
// But this should be a use of the (renamed) crate:
crate::bar::foo();
}

View File

@ -0,0 +1,21 @@
error: unused extern crate
--> $DIR/extern-crate-idiomatic-in-2018.rs:22:1
|
LL | extern crate edition_lint_paths;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
|
note: lint level defined here
--> $DIR/extern-crate-idiomatic-in-2018.rs:19:9
|
LL | #![deny(rust_2018_idioms)]
| ^^^^^^^^^^^^^^^^
= note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)]
error: `extern crate` is not idiomatic in the new edition
--> $DIR/extern-crate-idiomatic-in-2018.rs:25:1
|
LL | extern crate edition_lint_paths as bar;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
error: aborting due to 2 previous errors

View File

@ -16,12 +16,12 @@
#![warn(rust_2018_idioms)]
#![allow(unused_imports)]
use std as foo;
mod another {
use std as foo;
use std;
}
fn main() {}

View File

@ -1,31 +1,31 @@
warning: `extern crate` is unnecessary in the new edition
warning: unused extern crate
--> $DIR/removing-extern-crate.rs:19:1
|
LL | extern crate std as foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use std as foo;`
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
|
note: lint level defined here
--> $DIR/removing-extern-crate.rs:16:9
|
LL | #![warn(rust_2018_idioms)]
| ^^^^^^^^^^^^^^^^
= note: #[warn(unnecessary_extern_crates)] implied by #[warn(rust_2018_idioms)]
= note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
warning: `extern crate` is unnecessary in the new edition
warning: unused extern crate
--> $DIR/removing-extern-crate.rs:20:1
|
LL | extern crate core;
| ^^^^^^^^^^^^^^^^^^ help: remove it
warning: `extern crate` is unnecessary in the new edition
warning: unused extern crate
--> $DIR/removing-extern-crate.rs:23:5
|
LL | extern crate std as foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use std as foo;`
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
warning: `extern crate` is unnecessary in the new edition
warning: unused extern crate
--> $DIR/removing-extern-crate.rs:24:5
|
LL | extern crate std;
| ^^^^^^^^^^^^^^^^^ help: use `use`: `use std;`
| ^^^^^^^^^^^^^^^^^ help: remove it