Skip to content

Commit 8780d9c

Browse files
committed
auto merge of #17134 : vberger/rust/lint_unused_extern_crate, r=alexcrichton
This PR creates a new lint : ``unused_extern_crate``, which do pretty much the same thing as ``unused_import``, but for ``extern crate`` statements. It is related to feature request #10385. I adapted the code tracking used imports so that it tracks extern crates usage as well. This was mainly trial and error and while I believe all cases are covered, there might be some code I added that is useless (long compile times didn't give me the opportunity to check this in detail). Also, I removed some unused ``extern crate`` statements from the libs, that where spotted by this new lint.
2 parents 9c68679 + 8e61612 commit 8780d9c

File tree

6 files changed

+100
-7
lines changed

6 files changed

+100
-7
lines changed

src/librustc/lint/builtin.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1525,6 +1525,9 @@ impl LintPass for Stability {
15251525
declare_lint!(pub UNUSED_IMPORTS, Warn,
15261526
"imports that are never used")
15271527

1528+
declare_lint!(pub UNUSED_EXTERN_CRATE, Allow,
1529+
"extern crates that are never used")
1530+
15281531
declare_lint!(pub UNNECESSARY_QUALIFICATION, Allow,
15291532
"detects unnecessarily qualified names")
15301533

@@ -1569,6 +1572,7 @@ impl LintPass for HardwiredLints {
15691572
fn get_lints(&self) -> LintArray {
15701573
lint_array!(
15711574
UNUSED_IMPORTS,
1575+
UNUSED_EXTERN_CRATE,
15721576
UNNECESSARY_QUALIFICATION,
15731577
UNRECOGNIZED_LINT,
15741578
UNUSED_VARIABLE,

src/librustc/lint/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl LintStore {
201201

202202
add_lint_group!(sess, "unused",
203203
UNUSED_IMPORTS, UNUSED_VARIABLE, DEAD_ASSIGNMENT, DEAD_CODE,
204-
UNUSED_MUT, UNREACHABLE_CODE)
204+
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_EXTERN_CRATE)
205205

206206
// We have one lint pass defined in this module.
207207
self.register_pass(sess, false, box GatherNodeLevels as LintPassObject);

src/librustc/middle/resolve.rs

+63-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use middle::subst::{ParamSpace, FnSpace, TypeSpace};
2121
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
2222
use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
2323

24-
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate};
24+
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
2525
use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField};
2626
use syntax::ast::{ExprFnBlock, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
2727
use syntax::ast::{ExprPath, ExprProc, ExprStruct, ExprUnboxedFn, FnDecl};
@@ -899,6 +899,7 @@ struct Resolver<'a> {
899899
emit_errors: bool,
900900

901901
used_imports: HashSet<(NodeId, Namespace)>,
902+
used_crates: HashSet<CrateNum>,
902903
}
903904

904905
struct BuildReducedGraphVisitor<'a, 'b:'a> {
@@ -995,6 +996,7 @@ impl<'a> Resolver<'a> {
995996
export_map2: RefCell::new(NodeMap::new()),
996997
trait_map: NodeMap::new(),
997998
used_imports: HashSet::new(),
999+
used_crates: HashSet::new(),
9981000
external_exports: DefIdSet::new(),
9991001
last_private: NodeMap::new(),
10001002

@@ -2462,7 +2464,14 @@ impl<'a> Resolver<'a> {
24622464
debug!("(resolving single import) found \
24632465
import in ns {:?}", namespace);
24642466
let id = import_resolution.id(namespace);
2467+
// track used imports and extern crates as well
24652468
this.used_imports.insert((id, namespace));
2469+
match target_module.def_id.get() {
2470+
Some(DefId{krate: kid, ..}) => {
2471+
this.used_crates.insert(kid);
2472+
},
2473+
_ => {}
2474+
}
24662475
return BoundResult(target_module, bindings);
24672476
}
24682477
}
@@ -2505,6 +2514,11 @@ impl<'a> Resolver<'a> {
25052514
Some(module) => {
25062515
debug!("(resolving single import) found external \
25072516
module");
2517+
// track the module as used.
2518+
match module.def_id.get() {
2519+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
2520+
_ => {}
2521+
}
25082522
let name_bindings =
25092523
Rc::new(Resolver::create_name_bindings_from_module(
25102524
module));
@@ -3039,6 +3053,14 @@ impl<'a> Resolver<'a> {
30393053
(_, _) => {
30403054
search_module = module_def.clone();
30413055

3056+
// track extern crates for unused_extern_crate lint
3057+
match module_def.def_id.get() {
3058+
Some(did) => {
3059+
self.used_crates.insert(did.krate);
3060+
}
3061+
_ => {}
3062+
}
3063+
30423064
// Keep track of the closest
30433065
// private module used when
30443066
// resolving this import chain.
@@ -3222,7 +3244,12 @@ impl<'a> Resolver<'a> {
32223244
Some(target) => {
32233245
debug!("(resolving item in lexical scope) using \
32243246
import resolution");
3247+
// track used imports and extern crates as well
32253248
self.used_imports.insert((import_resolution.id(namespace), namespace));
3249+
match target.target_module.def_id.get() {
3250+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
3251+
_ => {}
3252+
}
32263253
return Success((target, false));
32273254
}
32283255
}
@@ -3501,7 +3528,12 @@ impl<'a> Resolver<'a> {
35013528
Some(target) => {
35023529
debug!("(resolving name in module) resolved to \
35033530
import");
3531+
// track used imports and extern crates as well
35043532
self.used_imports.insert((import_resolution.id(namespace), namespace));
3533+
match target.target_module.def_id.get() {
3534+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
3535+
_ => {}
3536+
}
35053537
return Success((target, true));
35063538
}
35073539
}
@@ -5068,7 +5100,14 @@ impl<'a> Resolver<'a> {
50685100
Some(def) => {
50695101
// Found it.
50705102
let id = import_resolution.id(namespace);
5103+
// track imports and extern crates as well
50715104
self.used_imports.insert((id, namespace));
5105+
match target.target_module.def_id.get() {
5106+
Some(DefId{krate: kid, ..}) => {
5107+
self.used_crates.insert(kid);
5108+
},
5109+
_ => {}
5110+
}
50725111
return ImportNameDefinition(def, LastMod(AllPublic));
50735112
}
50745113
None => {
@@ -5092,6 +5131,8 @@ impl<'a> Resolver<'a> {
50925131
match module.def_id.get() {
50935132
None => {} // Continue.
50945133
Some(def_id) => {
5134+
// track used crates
5135+
self.used_crates.insert(def_id.krate);
50955136
let lp = if module.is_public {LastMod(AllPublic)} else {
50965137
LastMod(DependsOn(def_id))
50975138
};
@@ -5175,6 +5216,10 @@ impl<'a> Resolver<'a> {
51755216
},
51765217
_ => (),
51775218
}
5219+
match containing_module.def_id.get() {
5220+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
5221+
_ => {}
5222+
}
51785223
return Some(def);
51795224
}
51805225

@@ -5794,6 +5839,10 @@ impl<'a> Resolver<'a> {
57945839
if self.trait_item_map.borrow().contains_key(&(name, did)) {
57955840
add_trait_info(&mut found_traits, did, name);
57965841
self.used_imports.insert((import.type_id, TypeNS));
5842+
match target.target_module.def_id.get() {
5843+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
5844+
_ => {}
5845+
}
57975846
}
57985847
}
57995848

@@ -5866,10 +5915,22 @@ impl<'a> Resolver<'a> {
58665915
if vi.span == DUMMY_SP { return }
58675916

58685917
match vi.node {
5869-
ViewItemExternCrate(..) => {} // ignore
5918+
ViewItemExternCrate(_, _, id) => {
5919+
match self.session.cstore.find_extern_mod_stmt_cnum(id)
5920+
{
5921+
Some(crate_num) => if !self.used_crates.contains(&crate_num) {
5922+
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATE,
5923+
id,
5924+
vi.span,
5925+
"unused extern crate".to_string());
5926+
},
5927+
_ => {}
5928+
}
5929+
},
58705930
ViewItemUse(ref p) => {
58715931
match p.node {
58725932
ViewPathSimple(_, _, id) => self.finalize_import(id, p.span),
5933+
58735934
ViewPathList(_, ref list, _) => {
58745935
for i in list.iter() {
58755936
self.finalize_import(i.node.id(), i.span);

src/librustc_back/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
#[phase(plugin, link)]
3737
extern crate log;
3838
extern crate syntax;
39-
extern crate libc;
40-
extern crate flate;
4139
extern crate serialize;
4240

4341
pub mod abi;

src/libsyntax/diagnostic.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
extern crate libc;
12-
1311
use codemap::{Pos, Span};
1412
use codemap;
1513
use diagnostics;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2014 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+
#![feature(globs)]
12+
#![deny(unused_extern_crate)]
13+
#![allow(unused_variable)]
14+
15+
extern crate libc; //~ ERROR: unused extern crate
16+
17+
extern crate "collections" as collecs; // no error, it is used
18+
19+
extern crate rand; // no error, the use marks it as used
20+
// even if imported objects aren't used
21+
22+
extern crate time; // no error, the use * marks it as used
23+
24+
#[allow(unused_imports)]
25+
use rand::isaac::IsaacRng;
26+
27+
use time::*;
28+
29+
fn main() {
30+
let x: collecs::vec::Vec<uint> = Vec::new();
31+
let y = now();
32+
}

0 commit comments

Comments
 (0)