diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f816ba9ab8143..1e48a54e018d6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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 { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 13df1ced6032e..7835d4e782c43 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -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)); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index ebc59964172ac..b7c66398f8500 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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, id: NodeId }, Inherited, } @@ -1964,7 +1964,7 @@ impl Visibility { match self { &Public | &Inherited => false, - &Crate | + &Crate(_) | &Restricted { .. } => true, } } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 4bee4f9add025..2cf627fdc162f 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -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<()> { diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 9b202f55f3c0a..397638fc55d4b 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -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> for hir::Visibility { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, @@ -758,10 +763,12 @@ impl<'a> HashStable> 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); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 646c60c139c85..419bffcae0643 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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. diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 8a0850595c889..79c7a79114761 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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; diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index c5994d0536ee0..d6ce5b2ea57fe 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -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: // diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index bff849d7ae8e9..41adde0d4a188 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -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,70 +80,138 @@ 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 = + 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; } - } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - } + // 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; + } - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + // 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(); } } -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()); - } +struct CollectExternCrateVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + crates_to_lint: &'a mut Vec, +} - let mut visitor = CheckVisitor { tcx, used_trait_imports }; - tcx.hir.krate().visit_all_item_likes(&mut visitor); +struct ExternCrateToLint { + /// def-id of the extern crate + def_id: DefId, - 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 + /// 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, +} + +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, + } + ); } - 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); + } + + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } + diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2e3ea3de7b0b7..a57f3a42939ee 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3030,7 +3030,7 @@ impl Clean> 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); diff --git a/src/test/compile-fail/edition-extern-crate-allowed.rs b/src/test/compile-fail/edition-extern-crate-allowed.rs index 286ee896161a6..7368564e250d1 100644 --- a/src/test/compile-fail/edition-extern-crate-allowed.rs +++ b/src/test/compile-fail/edition-extern-crate-allowed.rs @@ -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() {} diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.rs b/src/test/ui-fulldeps/unnecessary-extern-crate.rs index fc6cb6bd053e6..0811c79b0a4b9 100644 --- a/src/test/ui-fulldeps/unnecessary-extern-crate.rs +++ b/src/test/ui-fulldeps/unnecessary-extern-crate.rs @@ -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` +//~^ 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 unnecessary in the new edition -//~| HELP use `pub use` +//~^ 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(); } +} diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr index b9ccf5b19e03a..a4307112157b0 100644 --- a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr +++ b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr @@ -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 | pub(crate) extern crate libc as a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(crate) use` + +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:38:1 + | +LL | crate extern crate libc as b; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `crate use` + +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:43:5 + | +LL | pub(in crate::foo) extern crate libc as c; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo) use` + +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: use `use`: `use alloc;` + | ^^^^^^^^^^^^^^^^^^^ help: remove it -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:37:5 +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:55:5 | 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:40:5 +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:59:5 | LL | pub extern crate test; - | ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test;` + | ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use` -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:43:5 +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: 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:47:9 +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: `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 10 previous errors +error: aborting due to 15 previous errors diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/rfc-2166-underscore-imports/basic.stderr index 4530d0fa604aa..c12c74b50e264 100644 --- a/src/test/ui/rfc-2166-underscore-imports/basic.stderr +++ b/src/test/ui/rfc-2166-underscore-imports/basic.stderr @@ -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 diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed new file mode 100644 index 0000000000000..4f99c1240f8f4 --- /dev/null +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed @@ -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 or the MIT license +// , 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(); +} + diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs new file mode 100644 index 0000000000000..9c1235a296799 --- /dev/null +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs @@ -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 or the MIT license +// , 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(); +} + diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr new file mode 100644 index 0000000000000..b3afa2bd1d592 --- /dev/null +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr @@ -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 + diff --git a/src/test/ui/suggestions/removing-extern-crate.fixed b/src/test/ui/suggestions/removing-extern-crate.fixed index 723137f5db0c1..83b35cec80956 100644 --- a/src/test/ui/suggestions/removing-extern-crate.fixed +++ b/src/test/ui/suggestions/removing-extern-crate.fixed @@ -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() {} diff --git a/src/test/ui/suggestions/removing-extern-crate.stderr b/src/test/ui/suggestions/removing-extern-crate.stderr index 39d22de02776c..f2eed27a26693 100644 --- a/src/test/ui/suggestions/removing-extern-crate.stderr +++ b/src/test/ui/suggestions/removing-extern-crate.stderr @@ -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