Skip to content

Commit 9f8ec42

Browse files
committed
New lint : unused_extern_crate. #10385
1 parent 805cf81 commit 9f8ec42

File tree

4 files changed

+100
-3
lines changed

4 files changed

+100
-3
lines changed

src/librustc/lint/builtin.rs

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 63 additions & 2 deletions
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> {
@@ -987,6 +988,7 @@ impl<'a> Resolver<'a> {
987988
export_map2: RefCell::new(NodeMap::new()),
988989
trait_map: NodeMap::new(),
989990
used_imports: HashSet::new(),
991+
used_crates: HashSet::new(),
990992
external_exports: DefIdSet::new(),
991993
last_private: NodeMap::new(),
992994

@@ -2453,7 +2455,14 @@ impl<'a> Resolver<'a> {
24532455
debug!("(resolving single import) found \
24542456
import in ns {:?}", namespace);
24552457
let id = import_resolution.id(namespace);
2458+
// track used imports and extern crates as well
24562459
this.used_imports.insert((id, namespace));
2460+
match target_module.def_id.get() {
2461+
Some(DefId{krate: kid, ..}) => {
2462+
this.used_crates.insert(kid);
2463+
},
2464+
_ => {}
2465+
}
24572466
return BoundResult(target_module, bindings);
24582467
}
24592468
}
@@ -2496,6 +2505,11 @@ impl<'a> Resolver<'a> {
24962505
Some(module) => {
24972506
debug!("(resolving single import) found external \
24982507
module");
2508+
// track the module as used.
2509+
match module.def_id.get() {
2510+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
2511+
_ => {}
2512+
}
24992513
let name_bindings =
25002514
Rc::new(Resolver::create_name_bindings_from_module(
25012515
module));
@@ -3030,6 +3044,14 @@ impl<'a> Resolver<'a> {
30303044
(_, _) => {
30313045
search_module = module_def.clone();
30323046

3047+
// track extern crates for unused_extern_crate lint
3048+
match module_def.def_id.get() {
3049+
Some(did) => {
3050+
self.used_crates.insert(did.krate);
3051+
}
3052+
_ => {}
3053+
}
3054+
30333055
// Keep track of the closest
30343056
// private module used when
30353057
// resolving this import chain.
@@ -3213,7 +3235,12 @@ impl<'a> Resolver<'a> {
32133235
Some(target) => {
32143236
debug!("(resolving item in lexical scope) using \
32153237
import resolution");
3238+
// track used imports and extern crates as well
32163239
self.used_imports.insert((import_resolution.id(namespace), namespace));
3240+
match target.target_module.def_id.get() {
3241+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
3242+
_ => {}
3243+
}
32173244
return Success((target, false));
32183245
}
32193246
}
@@ -3492,7 +3519,12 @@ impl<'a> Resolver<'a> {
34923519
Some(target) => {
34933520
debug!("(resolving name in module) resolved to \
34943521
import");
3522+
// track used imports and extern crates as well
34953523
self.used_imports.insert((import_resolution.id(namespace), namespace));
3524+
match target.target_module.def_id.get() {
3525+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
3526+
_ => {}
3527+
}
34963528
return Success((target, true));
34973529
}
34983530
}
@@ -5061,7 +5093,14 @@ impl<'a> Resolver<'a> {
50615093
Some(def) => {
50625094
// Found it.
50635095
let id = import_resolution.id(namespace);
5096+
// track imports and extern crates as well
50645097
self.used_imports.insert((id, namespace));
5098+
match target.target_module.def_id.get() {
5099+
Some(DefId{krate: kid, ..}) => {
5100+
self.used_crates.insert(kid);
5101+
},
5102+
_ => {}
5103+
}
50655104
return ImportNameDefinition(def, LastMod(AllPublic));
50665105
}
50675106
None => {
@@ -5085,6 +5124,8 @@ impl<'a> Resolver<'a> {
50855124
match module.def_id.get() {
50865125
None => {} // Continue.
50875126
Some(def_id) => {
5127+
// track used crates
5128+
self.used_crates.insert(def_id.krate);
50885129
let lp = if module.is_public {LastMod(AllPublic)} else {
50895130
LastMod(DependsOn(def_id))
50905131
};
@@ -5168,6 +5209,10 @@ impl<'a> Resolver<'a> {
51685209
},
51695210
_ => (),
51705211
}
5212+
match containing_module.def_id.get() {
5213+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
5214+
_ => {}
5215+
}
51715216
return Some(def);
51725217
}
51735218

@@ -5787,6 +5832,10 @@ impl<'a> Resolver<'a> {
57875832
if self.trait_item_map.borrow().contains_key(&(name, did)) {
57885833
add_trait_info(&mut found_traits, did, name);
57895834
self.used_imports.insert((import.type_id, TypeNS));
5835+
match target.target_module.def_id.get() {
5836+
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
5837+
_ => {}
5838+
}
57905839
}
57915840
}
57925841

@@ -5859,10 +5908,22 @@ impl<'a> Resolver<'a> {
58595908
if vi.span == DUMMY_SP { return }
58605909

58615910
match vi.node {
5862-
ViewItemExternCrate(..) => {} // ignore
5911+
ViewItemExternCrate(_, _, id) => {
5912+
match self.session.cstore.find_extern_mod_stmt_cnum(id)
5913+
{
5914+
Some(crate_num) => if !self.used_crates.contains(&crate_num) {
5915+
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATE,
5916+
id,
5917+
vi.span,
5918+
"unused extern crate".to_string());
5919+
},
5920+
_ => {}
5921+
}
5922+
},
58635923
ViewItemUse(ref p) => {
58645924
match p.node {
58655925
ViewPathSimple(_, _, id) => self.finalize_import(id, p.span),
5926+
58665927
ViewPathList(_, ref list, _) => {
58675928
for i in list.iter() {
58685929
self.finalize_import(i.node.id(), i.span);
Lines changed: 32 additions & 0 deletions
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)