Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1b3d737

Browse files
committedJun 2, 2018
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 #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 #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 #51177 - [x] we also don't do the `pub use` rewrite thang (#51013) Spun off from #51010 Fixes #50672 r? @alexcrichton
2 parents 2954cb5 + b37cc85 commit 1b3d737

File tree

19 files changed

+421
-202
lines changed

19 files changed

+421
-202
lines changed
 

‎src/librustc/hir/lowering.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2433,7 +2433,7 @@ impl<'a> LoweringContext<'a> {
24332433
self.with_hir_id_owner(new_id, |this| {
24342434
let vis = match vis {
24352435
hir::Visibility::Public => hir::Visibility::Public,
2436-
hir::Visibility::Crate => hir::Visibility::Crate,
2436+
hir::Visibility::Crate(sugar) => hir::Visibility::Crate(sugar),
24372437
hir::Visibility::Inherited => hir::Visibility::Inherited,
24382438
hir::Visibility::Restricted { ref path, id: _ } => {
24392439
hir::Visibility::Restricted {
@@ -3704,7 +3704,7 @@ impl<'a> LoweringContext<'a> {
37043704
) -> hir::Visibility {
37053705
match v.node {
37063706
VisibilityKind::Public => hir::Public,
3707-
VisibilityKind::Crate(..) => hir::Visibility::Crate,
3707+
VisibilityKind::Crate(sugar) => hir::Visibility::Crate(sugar),
37083708
VisibilityKind::Restricted { ref path, id, .. } => hir::Visibility::Restricted {
37093709
path: P(self.lower_path(id, path, ParamMode::Explicit)),
37103710
id: if let Some(owner) = explicit_owner {

‎src/librustc/hir/map/collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
463463
fn visit_vis(&mut self, visibility: &'hir Visibility) {
464464
match *visibility {
465465
Visibility::Public |
466-
Visibility::Crate |
466+
Visibility::Crate(_) |
467467
Visibility::Inherited => {}
468468
Visibility::Restricted { id, .. } => {
469469
self.insert(id, NodeVisibility(visibility));

‎src/librustc/hir/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use mir::mono::Linkage;
3535
use syntax_pos::{Span, DUMMY_SP};
3636
use syntax::codemap::{self, Spanned};
3737
use rustc_target::spec::abi::Abi;
38-
use syntax::ast::{self, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
38+
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
3939
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
4040
use syntax::attr::InlineAttr;
4141
use syntax::ext::hygiene::SyntaxContext;
@@ -1953,7 +1953,7 @@ pub struct PolyTraitRef {
19531953
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
19541954
pub enum Visibility {
19551955
Public,
1956-
Crate,
1956+
Crate(CrateSugar),
19571957
Restricted { path: P<Path>, id: NodeId },
19581958
Inherited,
19591959
}
@@ -1964,7 +1964,7 @@ impl Visibility {
19641964
match self {
19651965
&Public |
19661966
&Inherited => false,
1967-
&Crate |
1967+
&Crate(_) |
19681968
&Restricted { .. } => true,
19691969
}
19701970
}

‎src/librustc/hir/print.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -801,15 +801,25 @@ impl<'a> State<'a> {
801801

802802
pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
803803
match *vis {
804-
hir::Public => self.word_nbsp("pub"),
805-
hir::Visibility::Crate => self.word_nbsp("pub(crate)"),
804+
hir::Public => self.word_nbsp("pub")?,
805+
hir::Visibility::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate")?,
806+
hir::Visibility::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)")?,
806807
hir::Visibility::Restricted { ref path, .. } => {
807808
self.s.word("pub(")?;
808-
self.print_path(path, false)?;
809-
self.word_nbsp(")")
809+
if path.segments.len() == 1 && path.segments[0].name == keywords::Super.name() {
810+
// Special case: `super` can print like `pub(super)`.
811+
self.s.word("super")?;
812+
} else {
813+
// Everything else requires `in` at present.
814+
self.word_nbsp("in")?;
815+
self.print_path(path, false)?;
816+
}
817+
self.word_nbsp(")")?;
810818
}
811-
hir::Inherited => Ok(()),
819+
hir::Inherited => ()
812820
}
821+
822+
Ok(())
813823
}
814824

815825
pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {

‎src/librustc/ich/impls_hir.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,17 +751,24 @@ impl_stable_hash_for!(enum hir::ImplItemKind {
751751
Type(t)
752752
});
753753

754+
impl_stable_hash_for!(enum ::syntax::ast::CrateSugar {
755+
JustCrate,
756+
PubCrate,
757+
});
758+
754759
impl<'a> HashStable<StableHashingContext<'a>> for hir::Visibility {
755760
fn hash_stable<W: StableHasherResult>(&self,
756761
hcx: &mut StableHashingContext<'a>,
757762
hasher: &mut StableHasher<W>) {
758763
mem::discriminant(self).hash_stable(hcx, hasher);
759764
match *self {
760765
hir::Visibility::Public |
761-
hir::Visibility::Crate |
762766
hir::Visibility::Inherited => {
763767
// No fields to hash.
764768
}
769+
hir::Visibility::Crate(sugar) => {
770+
sugar.hash_stable(hcx, hasher);
771+
}
765772
hir::Visibility::Restricted { ref path, id } => {
766773
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
767774
id.hash_stable(hcx, hasher);

‎src/librustc/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ impl Visibility {
270270
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
271271
match *visibility {
272272
hir::Public => Visibility::Public,
273-
hir::Visibility::Crate => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
273+
hir::Visibility::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
274274
hir::Visibility::Restricted { ref path, .. } => match path.def {
275275
// If there is no resolution, `resolve` will have already reported an error, so
276276
// assume that the visibility is public to avoid reporting more privacy errors.

‎src/librustc_lint/builtin.rs

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,72 +1548,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
15481548
}
15491549
}
15501550

1551-
declare_lint! {
1552-
pub UNNECESSARY_EXTERN_CRATES,
1553-
Allow,
1554-
"suggest removing `extern crate` for the 2018 edition"
1555-
}
1556-
1557-
pub struct ExternCrate(/* depth */ u32);
1558-
1559-
impl ExternCrate {
1560-
pub fn new() -> Self {
1561-
ExternCrate(0)
1562-
}
1563-
}
1564-
1565-
impl LintPass for ExternCrate {
1566-
fn get_lints(&self) -> LintArray {
1567-
lint_array!(UNNECESSARY_EXTERN_CRATES)
1568-
}
1569-
}
1570-
1571-
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExternCrate {
1572-
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
1573-
if !cx.tcx.features().extern_absolute_paths {
1574-
return
1575-
}
1576-
if let hir::ItemExternCrate(ref orig) = it.node {
1577-
if it.attrs.iter().any(|a| a.check_name("macro_use")) {
1578-
return
1579-
}
1580-
let mut err = cx.struct_span_lint(UNNECESSARY_EXTERN_CRATES,
1581-
it.span, "`extern crate` is unnecessary in the new edition");
1582-
if it.vis == hir::Visibility::Public || self.0 > 1 || orig.is_some() {
1583-
let pub_ = if it.vis == hir::Visibility::Public {
1584-
"pub "
1585-
} else {
1586-
""
1587-
};
1588-
1589-
let help = format!("use `{}use`", pub_);
1590-
1591-
if let Some(orig) = orig {
1592-
err.span_suggestion(it.span, &help,
1593-
format!("{}use {} as {};", pub_, orig, it.name));
1594-
} else {
1595-
err.span_suggestion(it.span, &help,
1596-
format!("{}use {};", pub_, it.name));
1597-
}
1598-
} else {
1599-
err.span_suggestion(it.span, "remove it", "".into());
1600-
}
1601-
1602-
err.emit();
1603-
}
1604-
}
1605-
1606-
fn check_mod(&mut self, _: &LateContext, _: &hir::Mod,
1607-
_: Span, _: ast::NodeId) {
1608-
self.0 += 1;
1609-
}
1610-
1611-
fn check_mod_post(&mut self, _: &LateContext, _: &hir::Mod,
1612-
_: Span, _: ast::NodeId) {
1613-
self.0 += 1;
1614-
}
1615-
}
1616-
16171551
/// Lint for trait and lifetime bounds that don't depend on type parameters
16181552
/// which either do nothing, or stop the item from being used.
16191553
pub struct TrivialConstraints;

‎src/librustc_lint/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
145145
TypeLimits,
146146
MissingDoc,
147147
MissingDebugImplementations,
148-
ExternCrate,
149148
);
150149

151150
add_lint_group!(sess,
@@ -185,7 +184,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
185184
"rust_2018_idioms",
186185
BARE_TRAIT_OBJECTS,
187186
UNREACHABLE_PUB,
188-
UNNECESSARY_EXTERN_CRATES);
187+
UNUSED_EXTERN_CRATES);
189188

190189
// Guidelines for creating a future incompatibility lint:
191190
//

‎src/librustc_typeck/check_unused.rs

Lines changed: 159 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,46 @@ use rustc::ty::TyCtxt;
1414
use syntax::ast;
1515
use syntax_pos::{Span, DUMMY_SP};
1616

17-
use rustc::hir::def_id::LOCAL_CRATE;
17+
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
1818
use rustc::hir::itemlikevisit::ItemLikeVisitor;
19+
use rustc::hir::print::visibility_qualified;
1920
use rustc::hir;
2021
use rustc::util::nodemap::DefIdSet;
2122

23+
use rustc_data_structures::fx::FxHashMap;
24+
25+
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
26+
let mut used_trait_imports = DefIdSet();
27+
for &body_id in tcx.hir.krate().bodies.keys() {
28+
let item_def_id = tcx.hir.body_owner_def_id(body_id);
29+
let imports = tcx.used_trait_imports(item_def_id);
30+
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
31+
used_trait_imports.extend(imports.iter());
32+
}
33+
34+
let mut visitor = CheckVisitor { tcx, used_trait_imports };
35+
tcx.hir.krate().visit_all_item_likes(&mut visitor);
36+
37+
unused_crates_lint(tcx);
38+
}
39+
40+
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
41+
fn visit_item(&mut self, item: &hir::Item) {
42+
if item.vis == hir::Public || item.span == DUMMY_SP {
43+
return;
44+
}
45+
if let hir::ItemUse(ref path, _) = item.node {
46+
self.check_import(item.id, path.span);
47+
}
48+
}
49+
50+
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
51+
}
52+
53+
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
54+
}
55+
}
56+
2257
struct CheckVisitor<'a, 'tcx: 'a> {
2358
tcx: TyCtxt<'a, 'tcx, 'tcx>,
2459
used_trait_imports: DefIdSet,
@@ -45,70 +80,138 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
4580
}
4681
}
4782

48-
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
49-
fn visit_item(&mut self, item: &hir::Item) {
50-
if item.vis == hir::Public || item.span == DUMMY_SP {
51-
return;
83+
fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
84+
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
85+
86+
// Collect first the crates that are completely unused. These we
87+
// can always suggest removing (no matter which edition we are
88+
// in).
89+
let unused_extern_crates: FxHashMap<DefId, Span> =
90+
tcx.maybe_unused_extern_crates(LOCAL_CRATE)
91+
.iter()
92+
.filter(|&&(def_id, _)| {
93+
// The `def_id` here actually was calculated during resolution (at least
94+
// at the time of this writing) and is being shipped to us via a side
95+
// channel of the tcx. There may have been extra expansion phases,
96+
// however, which ended up removing the `def_id` *after* expansion such
97+
// as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey)
98+
//
99+
// As a result we need to verify that `def_id` is indeed still valid for
100+
// our AST and actually present in the HIR map. If it's not there then
101+
// there's safely nothing to warn about, and otherwise we carry on with
102+
// our execution.
103+
//
104+
// Note that if we carry through to the `extern_mod_stmt_cnum` query
105+
// below it'll cause a panic because `def_id` is actually bogus at this
106+
// point in time otherwise.
107+
if let Some(id) = tcx.hir.as_local_node_id(def_id) {
108+
if tcx.hir.find(id).is_none() {
109+
return false;
110+
}
111+
}
112+
true
113+
})
114+
.filter(|&&(def_id, _)| {
115+
let cnum = tcx.extern_mod_stmt_cnum(def_id).unwrap();
116+
!tcx.is_compiler_builtins(cnum)
117+
&& !tcx.is_panic_runtime(cnum)
118+
&& !tcx.has_global_allocator(cnum)
119+
})
120+
.cloned()
121+
.collect();
122+
123+
// Collect all the extern crates (in a reliable order).
124+
let mut crates_to_lint = vec![];
125+
tcx.hir.krate().visit_all_item_likes(&mut CollectExternCrateVisitor {
126+
tcx,
127+
crates_to_lint: &mut crates_to_lint,
128+
});
129+
130+
for extern_crate in &crates_to_lint {
131+
assert!(extern_crate.def_id.is_local());
132+
133+
// If the crate is fully unused, we suggest removing it altogether.
134+
// We do this in any edition.
135+
if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
136+
assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
137+
let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
138+
let id = tcx.hir.hir_to_node_id(hir_id);
139+
let msg = "unused extern crate";
140+
tcx.struct_span_lint_node(lint, id, span, msg)
141+
.span_suggestion_short(span, "remove it", "".to_string())
142+
.emit();
143+
continue;
52144
}
53-
if let hir::ItemUse(ref path, _) = item.node {
54-
self.check_import(item.id, path.span);
145+
146+
// If we are not in Rust 2018 edition, then we don't make any further
147+
// suggestions.
148+
if !tcx.sess.rust_2018() {
149+
continue;
55150
}
56-
}
57151

58-
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
59-
}
152+
// If the extern crate has any attributes, they may have funky
153+
// semantics we can't faithfully represent using `use` (most
154+
// notably `#[macro_use]`). Ignore it.
155+
if !tcx.get_attrs(extern_crate.def_id).is_empty() {
156+
continue;
157+
}
60158

61-
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
159+
// Otherwise, we can convert it into a `use` of some kind.
160+
let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
161+
let id = tcx.hir.hir_to_node_id(hir_id);
162+
let item = tcx.hir.expect_item(id);
163+
let msg = "`extern crate` is not idiomatic in the new edition";
164+
let help = format!(
165+
"convert it to a `{}`",
166+
visibility_qualified(&item.vis, "use")
167+
);
168+
let base_replacement = match extern_crate.orig_name {
169+
Some(orig_name) => format!("use {} as {};", orig_name, item.name),
170+
None => format!("use {};", item.name),
171+
};
172+
let replacement = visibility_qualified(&item.vis, &base_replacement);
173+
tcx.struct_span_lint_node(lint, id, extern_crate.span, msg)
174+
.span_suggestion_short(extern_crate.span, &help, replacement)
175+
.emit();
62176
}
63177
}
64178

65-
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
66-
let mut used_trait_imports = DefIdSet();
67-
for &body_id in tcx.hir.krate().bodies.keys() {
68-
let item_def_id = tcx.hir.body_owner_def_id(body_id);
69-
let imports = tcx.used_trait_imports(item_def_id);
70-
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
71-
used_trait_imports.extend(imports.iter());
72-
}
179+
struct CollectExternCrateVisitor<'a, 'tcx: 'a> {
180+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
181+
crates_to_lint: &'a mut Vec<ExternCrateToLint>,
182+
}
73183

74-
let mut visitor = CheckVisitor { tcx, used_trait_imports };
75-
tcx.hir.krate().visit_all_item_likes(&mut visitor);
184+
struct ExternCrateToLint {
185+
/// def-id of the extern crate
186+
def_id: DefId,
76187

77-
for &(def_id, span) in tcx.maybe_unused_extern_crates(LOCAL_CRATE).iter() {
78-
// The `def_id` here actually was calculated during resolution (at least
79-
// at the time of this writing) and is being shipped to us via a side
80-
// channel of the tcx. There may have been extra expansion phases,
81-
// however, which ended up removing the `def_id` *after* expansion such
82-
// as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey)
83-
//
84-
// As a result we need to verify that `def_id` is indeed still valid for
85-
// our AST and actually present in the HIR map. If it's not there then
86-
// there's safely nothing to warn about, and otherwise we carry on with
87-
// our execution.
88-
//
89-
// Note that if we carry through to the `extern_mod_stmt_cnum` query
90-
// below it'll cause a panic because `def_id` is actually bogus at this
91-
// point in time otherwise.
92-
if let Some(id) = tcx.hir.as_local_node_id(def_id) {
93-
if tcx.hir.find(id).is_none() {
94-
continue
95-
}
96-
}
97-
let cnum = tcx.extern_mod_stmt_cnum(def_id).unwrap();
98-
if tcx.is_compiler_builtins(cnum) {
99-
continue
100-
}
101-
if tcx.is_panic_runtime(cnum) {
102-
continue
103-
}
104-
if tcx.has_global_allocator(cnum) {
105-
continue
188+
/// span from the item
189+
span: Span,
190+
191+
/// if `Some`, then this is renamed (`extern crate orig_name as
192+
/// crate_name`), and -- perhaps surprisingly -- this stores the
193+
/// *original* name (`item.name` will contain the new name)
194+
orig_name: Option<ast::Name>,
195+
}
196+
197+
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
198+
fn visit_item(&mut self, item: &hir::Item) {
199+
if let hir::ItemExternCrate(orig_name) = item.node {
200+
let extern_crate_def_id = self.tcx.hir.local_def_id(item.id);
201+
self.crates_to_lint.push(
202+
ExternCrateToLint {
203+
def_id: extern_crate_def_id,
204+
span: item.span,
205+
orig_name,
206+
}
207+
);
106208
}
107-
assert_eq!(def_id.krate, LOCAL_CRATE);
108-
let hir_id = tcx.hir.definitions().def_index_to_hir_id(def_id.index);
109-
let id = tcx.hir.hir_to_node_id(hir_id);
110-
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
111-
let msg = "unused extern crate";
112-
tcx.lint_node(lint, id, span, msg);
209+
}
210+
211+
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
212+
}
213+
214+
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
113215
}
114216
}
217+

‎src/librustdoc/clean/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3030,7 +3030,7 @@ impl Clean<Option<Visibility>> for hir::Visibility {
30303030
Some(match *self {
30313031
hir::Visibility::Public => Visibility::Public,
30323032
hir::Visibility::Inherited => Visibility::Inherited,
3033-
hir::Visibility::Crate => Visibility::Crate,
3033+
hir::Visibility::Crate(_) => Visibility::Crate,
30343034
hir::Visibility::Restricted { ref path, .. } => {
30353035
let path = path.clean(cx);
30363036
let did = register_def(cx, path.def);

‎src/test/compile-fail/edition-extern-crate-allowed.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
// compile-flags: --edition 2015
1313
// compile-pass
1414

15-
#![deny(rust_2018_idioms)]
15+
#![warn(rust_2018_idioms)]
1616

1717
extern crate edition_extern_crate_allowed;
18+
//~^ WARNING unused extern crate
1819

1920
fn main() {}

‎src/test/ui-fulldeps/unnecessary-extern-crate.rs

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,48 +10,90 @@
1010

1111
// compile-flags: --edition 2018
1212

13-
#![deny(unnecessary_extern_crates)]
13+
#![deny(unused_extern_crates)]
1414
#![feature(alloc, test, libc)]
1515

1616
extern crate alloc;
17-
//~^ ERROR `extern crate` is unnecessary in the new edition
17+
//~^ ERROR unused extern crate
1818
//~| HELP remove
1919
extern crate alloc as x;
20-
//~^ ERROR `extern crate` is unnecessary in the new edition
21-
//~| HELP use `use`
20+
//~^ ERROR unused extern crate
21+
//~| HELP remove
2222

2323
#[macro_use]
2424
extern crate test;
25+
2526
pub extern crate test as y;
26-
//~^ ERROR `extern crate` is unnecessary in the new edition
27-
//~| HELP use `pub use`
27+
//~^ ERROR `extern crate` is not idiomatic in the new edition
28+
//~| HELP convert it to a `pub use`
29+
2830
pub extern crate libc;
29-
//~^ ERROR `extern crate` is unnecessary in the new edition
30-
//~| HELP use `pub use`
31+
//~^ ERROR `extern crate` is not idiomatic in the new edition
32+
//~| HELP convert it to a `pub use`
33+
34+
pub(crate) extern crate libc as a;
35+
//~^ ERROR `extern crate` is not idiomatic in the new edition
36+
//~| HELP convert it to a `pub(crate) use`
3137

38+
crate extern crate libc as b;
39+
//~^ ERROR `extern crate` is not idiomatic in the new edition
40+
//~| HELP convert it to a `crate use`
3241

3342
mod foo {
43+
pub(in crate::foo) extern crate libc as c;
44+
//~^ ERROR `extern crate` is not idiomatic in the new edition
45+
//~| HELP convert it to a `pub(in crate::foo) use`
46+
47+
pub(super) extern crate libc as d;
48+
//~^ ERROR `extern crate` is not idiomatic in the new edition
49+
//~| HELP convert it to a `pub(super) use`
50+
3451
extern crate alloc;
35-
//~^ ERROR `extern crate` is unnecessary in the new edition
36-
//~| HELP use `use`
52+
//~^ ERROR unused extern crate
53+
//~| HELP remove
54+
3755
extern crate alloc as x;
38-
//~^ ERROR `extern crate` is unnecessary in the new edition
39-
//~| HELP use `use`
56+
//~^ ERROR unused extern crate
57+
//~| HELP remove
58+
4059
pub extern crate test;
41-
//~^ ERROR `extern crate` is unnecessary in the new edition
42-
//~| HELP use `pub use`
60+
//~^ ERROR `extern crate` is not idiomatic in the new edition
61+
//~| HELP convert it
62+
4363
pub extern crate test as y;
44-
//~^ ERROR `extern crate` is unnecessary in the new edition
45-
//~| HELP use `pub use`
64+
//~^ ERROR `extern crate` is not idiomatic in the new edition
65+
//~| HELP convert it
66+
4667
mod bar {
4768
extern crate alloc;
48-
//~^ ERROR `extern crate` is unnecessary in the new edition
49-
//~| HELP use `use`
69+
//~^ ERROR unused extern crate
70+
//~| HELP remove
71+
5072
extern crate alloc as x;
51-
//~^ ERROR `extern crate` is unnecessary in the new edition
52-
//~| HELP use `use`
73+
//~^ ERROR unused extern crate
74+
//~| HELP remove
75+
76+
pub(in crate::foo::bar) extern crate libc as e;
77+
//~^ ERROR `extern crate` is not idiomatic in the new edition
78+
//~| HELP convert it to a `pub(in crate::foo::bar) use`
79+
80+
fn dummy() {
81+
unsafe {
82+
e::getpid();
83+
}
84+
}
85+
}
86+
87+
fn dummy() {
88+
unsafe {
89+
c::getpid();
90+
d::getpid();
91+
}
5392
}
5493
}
5594

5695

57-
fn main() {}
96+
fn main() {
97+
unsafe { a::getpid(); }
98+
unsafe { b::getpid(); }
99+
}
Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `extern crate` is unnecessary in the new edition
1+
error: unused extern crate
22
--> $DIR/unnecessary-extern-crate.rs:16:1
33
|
44
LL | extern crate alloc;
@@ -7,62 +7,92 @@ LL | extern crate alloc;
77
note: lint level defined here
88
--> $DIR/unnecessary-extern-crate.rs:13:9
99
|
10-
LL | #![deny(unnecessary_extern_crates)]
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
10+
LL | #![deny(unused_extern_crates)]
11+
| ^^^^^^^^^^^^^^^^^^^^
1212

13-
error: `extern crate` is unnecessary in the new edition
13+
error: unused extern crate
1414
--> $DIR/unnecessary-extern-crate.rs:19:1
1515
|
1616
LL | extern crate alloc as x;
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
1818

19-
error: `extern crate` is unnecessary in the new edition
20-
--> $DIR/unnecessary-extern-crate.rs:25:1
19+
error: `extern crate` is not idiomatic in the new edition
20+
--> $DIR/unnecessary-extern-crate.rs:26:1
2121
|
2222
LL | pub extern crate test as y;
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y;`
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
2424

25-
error: `extern crate` is unnecessary in the new edition
26-
--> $DIR/unnecessary-extern-crate.rs:28:1
25+
error: `extern crate` is not idiomatic in the new edition
26+
--> $DIR/unnecessary-extern-crate.rs:30:1
2727
|
2828
LL | pub extern crate libc;
29-
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use libc;`
29+
| ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
3030

31-
error: `extern crate` is unnecessary in the new edition
32-
--> $DIR/unnecessary-extern-crate.rs:34:5
31+
error: `extern crate` is not idiomatic in the new edition
32+
--> $DIR/unnecessary-extern-crate.rs:34:1
33+
|
34+
LL | pub(crate) extern crate libc as a;
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(crate) use`
36+
37+
error: `extern crate` is not idiomatic in the new edition
38+
--> $DIR/unnecessary-extern-crate.rs:38:1
39+
|
40+
LL | crate extern crate libc as b;
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `crate use`
42+
43+
error: `extern crate` is not idiomatic in the new edition
44+
--> $DIR/unnecessary-extern-crate.rs:43:5
45+
|
46+
LL | pub(in crate::foo) extern crate libc as c;
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo) use`
48+
49+
error: `extern crate` is not idiomatic in the new edition
50+
--> $DIR/unnecessary-extern-crate.rs:47:5
51+
|
52+
LL | pub(super) extern crate libc as d;
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(super) use`
54+
55+
error: unused extern crate
56+
--> $DIR/unnecessary-extern-crate.rs:51:5
3357
|
3458
LL | extern crate alloc;
35-
| ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc;`
59+
| ^^^^^^^^^^^^^^^^^^^ help: remove it
3660

37-
error: `extern crate` is unnecessary in the new edition
38-
--> $DIR/unnecessary-extern-crate.rs:37:5
61+
error: unused extern crate
62+
--> $DIR/unnecessary-extern-crate.rs:55:5
3963
|
4064
LL | extern crate alloc as x;
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
65+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
4266

43-
error: `extern crate` is unnecessary in the new edition
44-
--> $DIR/unnecessary-extern-crate.rs:40:5
67+
error: `extern crate` is not idiomatic in the new edition
68+
--> $DIR/unnecessary-extern-crate.rs:59:5
4569
|
4670
LL | pub extern crate test;
47-
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test;`
71+
| ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
4872

49-
error: `extern crate` is unnecessary in the new edition
50-
--> $DIR/unnecessary-extern-crate.rs:43:5
73+
error: `extern crate` is not idiomatic in the new edition
74+
--> $DIR/unnecessary-extern-crate.rs:63:5
5175
|
5276
LL | pub extern crate test as y;
53-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y;`
77+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
5478

55-
error: `extern crate` is unnecessary in the new edition
56-
--> $DIR/unnecessary-extern-crate.rs:47:9
79+
error: unused extern crate
80+
--> $DIR/unnecessary-extern-crate.rs:68:9
5781
|
5882
LL | extern crate alloc;
59-
| ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc;`
83+
| ^^^^^^^^^^^^^^^^^^^ help: remove it
6084

61-
error: `extern crate` is unnecessary in the new edition
62-
--> $DIR/unnecessary-extern-crate.rs:50:9
85+
error: unused extern crate
86+
--> $DIR/unnecessary-extern-crate.rs:72:9
6387
|
6488
LL | extern crate alloc as x;
65-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
89+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
90+
91+
error: `extern crate` is not idiomatic in the new edition
92+
--> $DIR/unnecessary-extern-crate.rs:76:9
93+
|
94+
LL | pub(in crate::foo::bar) extern crate libc as e;
95+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo::bar) use`
6696

67-
error: aborting due to 10 previous errors
97+
error: aborting due to 15 previous errors
6898

‎src/test/ui/rfc-2166-underscore-imports/basic.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ warning: unused extern crate
2020
--> $DIR/basic.rs:33:5
2121
|
2222
LL | extern crate core as _; //~ WARN unused extern crate
23-
| ^^^^^^^^^^^^^^^^^^^^^^^
23+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
2424
|
2525
note: lint level defined here
2626
--> $DIR/basic.rs:14:25
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:edition-lint-paths.rs
12+
// run-rustfix
13+
// compile-flags:--edition 2018
14+
15+
// The "normal case". Ideally we would remove the `extern crate` here,
16+
// but we don't.
17+
18+
#![feature(rust_2018_preview)]
19+
#![deny(rust_2018_idioms)]
20+
#![allow(dead_code)]
21+
22+
23+
//~^ ERROR unused extern crate
24+
25+
use edition_lint_paths as bar;
26+
//~^ ERROR `extern crate` is not idiomatic in the new edition
27+
28+
fn main() {
29+
// This is not considered to *use* the `extern crate` in Rust 2018:
30+
use edition_lint_paths::foo;
31+
foo();
32+
33+
// But this should be a use of the (renamed) crate:
34+
crate::bar::foo();
35+
}
36+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:edition-lint-paths.rs
12+
// run-rustfix
13+
// compile-flags:--edition 2018
14+
15+
// The "normal case". Ideally we would remove the `extern crate` here,
16+
// but we don't.
17+
18+
#![feature(rust_2018_preview)]
19+
#![deny(rust_2018_idioms)]
20+
#![allow(dead_code)]
21+
22+
extern crate edition_lint_paths;
23+
//~^ ERROR unused extern crate
24+
25+
extern crate edition_lint_paths as bar;
26+
//~^ ERROR `extern crate` is not idiomatic in the new edition
27+
28+
fn main() {
29+
// This is not considered to *use* the `extern crate` in Rust 2018:
30+
use edition_lint_paths::foo;
31+
foo();
32+
33+
// But this should be a use of the (renamed) crate:
34+
crate::bar::foo();
35+
}
36+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error: unused extern crate
2+
--> $DIR/extern-crate-idiomatic-in-2018.rs:22:1
3+
|
4+
LL | extern crate edition_lint_paths;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
6+
|
7+
note: lint level defined here
8+
--> $DIR/extern-crate-idiomatic-in-2018.rs:19:9
9+
|
10+
LL | #![deny(rust_2018_idioms)]
11+
| ^^^^^^^^^^^^^^^^
12+
= note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)]
13+
14+
error: `extern crate` is not idiomatic in the new edition
15+
--> $DIR/extern-crate-idiomatic-in-2018.rs:25:1
16+
|
17+
LL | extern crate edition_lint_paths as bar;
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
19+
20+
error: aborting due to 2 previous errors
21+

‎src/test/ui/suggestions/removing-extern-crate.fixed

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
#![warn(rust_2018_idioms)]
1717
#![allow(unused_imports)]
1818

19-
use std as foo;
19+
2020

2121

2222
mod another {
23-
use std as foo;
24-
use std;
23+
24+
2525
}
2626

2727
fn main() {}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
1-
warning: `extern crate` is unnecessary in the new edition
1+
warning: unused extern crate
22
--> $DIR/removing-extern-crate.rs:19:1
33
|
44
LL | extern crate std as foo;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use std as foo;`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
66
|
77
note: lint level defined here
88
--> $DIR/removing-extern-crate.rs:16:9
99
|
1010
LL | #![warn(rust_2018_idioms)]
1111
| ^^^^^^^^^^^^^^^^
12-
= note: #[warn(unnecessary_extern_crates)] implied by #[warn(rust_2018_idioms)]
12+
= note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
1313

14-
warning: `extern crate` is unnecessary in the new edition
14+
warning: unused extern crate
1515
--> $DIR/removing-extern-crate.rs:20:1
1616
|
1717
LL | extern crate core;
1818
| ^^^^^^^^^^^^^^^^^^ help: remove it
1919

20-
warning: `extern crate` is unnecessary in the new edition
20+
warning: unused extern crate
2121
--> $DIR/removing-extern-crate.rs:23:5
2222
|
2323
LL | extern crate std as foo;
24-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use std as foo;`
24+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
2525

26-
warning: `extern crate` is unnecessary in the new edition
26+
warning: unused extern crate
2727
--> $DIR/removing-extern-crate.rs:24:5
2828
|
2929
LL | extern crate std;
30-
| ^^^^^^^^^^^^^^^^^ help: use `use`: `use std;`
30+
| ^^^^^^^^^^^^^^^^^ help: remove it
3131

0 commit comments

Comments
 (0)
Please sign in to comment.