Skip to content

Commit

Permalink
auto merge of #17134 : vberger/rust/lint_unused_extern_crate, r=alexc…
Browse files Browse the repository at this point in the history
…richton

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.
  • Loading branch information
bors committed Sep 12, 2014
2 parents 9c68679 + 8e61612 commit 8780d9c
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,9 @@ impl LintPass for Stability {
declare_lint!(pub UNUSED_IMPORTS, Warn,
"imports that are never used")

declare_lint!(pub UNUSED_EXTERN_CRATE, Allow,
"extern crates that are never used")

declare_lint!(pub UNNECESSARY_QUALIFICATION, Allow,
"detects unnecessarily qualified names")

Expand Down Expand Up @@ -1569,6 +1572,7 @@ impl LintPass for HardwiredLints {
fn get_lints(&self) -> LintArray {
lint_array!(
UNUSED_IMPORTS,
UNUSED_EXTERN_CRATE,
UNNECESSARY_QUALIFICATION,
UNRECOGNIZED_LINT,
UNUSED_VARIABLE,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl LintStore {

add_lint_group!(sess, "unused",
UNUSED_IMPORTS, UNUSED_VARIABLE, DEAD_ASSIGNMENT, DEAD_CODE,
UNUSED_MUT, UNREACHABLE_CODE)
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_EXTERN_CRATE)

// We have one lint pass defined in this module.
self.register_pass(sess, false, box GatherNodeLevels as LintPassObject);
Expand Down
65 changes: 63 additions & 2 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use middle::subst::{ParamSpace, FnSpace, TypeSpace};
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};

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

used_imports: HashSet<(NodeId, Namespace)>,
used_crates: HashSet<CrateNum>,
}

struct BuildReducedGraphVisitor<'a, 'b:'a> {
Expand Down Expand Up @@ -995,6 +996,7 @@ impl<'a> Resolver<'a> {
export_map2: RefCell::new(NodeMap::new()),
trait_map: NodeMap::new(),
used_imports: HashSet::new(),
used_crates: HashSet::new(),
external_exports: DefIdSet::new(),
last_private: NodeMap::new(),

Expand Down Expand Up @@ -2462,7 +2464,14 @@ impl<'a> Resolver<'a> {
debug!("(resolving single import) found \
import in ns {:?}", namespace);
let id = import_resolution.id(namespace);
// track used imports and extern crates as well
this.used_imports.insert((id, namespace));
match target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => {
this.used_crates.insert(kid);
},
_ => {}
}
return BoundResult(target_module, bindings);
}
}
Expand Down Expand Up @@ -2505,6 +2514,11 @@ impl<'a> Resolver<'a> {
Some(module) => {
debug!("(resolving single import) found external \
module");
// track the module as used.
match module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
let name_bindings =
Rc::new(Resolver::create_name_bindings_from_module(
module));
Expand Down Expand Up @@ -3039,6 +3053,14 @@ impl<'a> Resolver<'a> {
(_, _) => {
search_module = module_def.clone();

// track extern crates for unused_extern_crate lint
match module_def.def_id.get() {
Some(did) => {
self.used_crates.insert(did.krate);
}
_ => {}
}

// Keep track of the closest
// private module used when
// resolving this import chain.
Expand Down Expand Up @@ -3222,7 +3244,12 @@ impl<'a> Resolver<'a> {
Some(target) => {
debug!("(resolving item in lexical scope) using \
import resolution");
// track used imports and extern crates as well
self.used_imports.insert((import_resolution.id(namespace), namespace));
match target.target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
return Success((target, false));
}
}
Expand Down Expand Up @@ -3501,7 +3528,12 @@ impl<'a> Resolver<'a> {
Some(target) => {
debug!("(resolving name in module) resolved to \
import");
// track used imports and extern crates as well
self.used_imports.insert((import_resolution.id(namespace), namespace));
match target.target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
return Success((target, true));
}
}
Expand Down Expand Up @@ -5068,7 +5100,14 @@ impl<'a> Resolver<'a> {
Some(def) => {
// Found it.
let id = import_resolution.id(namespace);
// track imports and extern crates as well
self.used_imports.insert((id, namespace));
match target.target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => {
self.used_crates.insert(kid);
},
_ => {}
}
return ImportNameDefinition(def, LastMod(AllPublic));
}
None => {
Expand All @@ -5092,6 +5131,8 @@ impl<'a> Resolver<'a> {
match module.def_id.get() {
None => {} // Continue.
Some(def_id) => {
// track used crates
self.used_crates.insert(def_id.krate);
let lp = if module.is_public {LastMod(AllPublic)} else {
LastMod(DependsOn(def_id))
};
Expand Down Expand Up @@ -5175,6 +5216,10 @@ impl<'a> Resolver<'a> {
},
_ => (),
}
match containing_module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
return Some(def);
}

Expand Down Expand Up @@ -5794,6 +5839,10 @@ impl<'a> Resolver<'a> {
if self.trait_item_map.borrow().contains_key(&(name, did)) {
add_trait_info(&mut found_traits, did, name);
self.used_imports.insert((import.type_id, TypeNS));
match target.target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
}
}

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

match vi.node {
ViewItemExternCrate(..) => {} // ignore
ViewItemExternCrate(_, _, id) => {
match self.session.cstore.find_extern_mod_stmt_cnum(id)
{
Some(crate_num) => if !self.used_crates.contains(&crate_num) {
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATE,
id,
vi.span,
"unused extern crate".to_string());
},
_ => {}
}
},
ViewItemUse(ref p) => {
match p.node {
ViewPathSimple(_, _, id) => self.finalize_import(id, p.span),

ViewPathList(_, ref list, _) => {
for i in list.iter() {
self.finalize_import(i.node.id(), i.span);
Expand Down
2 changes: 0 additions & 2 deletions src/librustc_back/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@
#[phase(plugin, link)]
extern crate log;
extern crate syntax;
extern crate libc;
extern crate flate;
extern crate serialize;

pub mod abi;
Expand Down
2 changes: 0 additions & 2 deletions src/libsyntax/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use codemap::{Pos, Span};
use codemap;
use diagnostics;
Expand Down
32 changes: 32 additions & 0 deletions src/test/compile-fail/lint-unused-extern-crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2014 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.

#![feature(globs)]
#![deny(unused_extern_crate)]
#![allow(unused_variable)]

extern crate libc; //~ ERROR: unused extern crate

extern crate "collections" as collecs; // no error, it is used

extern crate rand; // no error, the use marks it as used
// even if imported objects aren't used

extern crate time; // no error, the use * marks it as used

#[allow(unused_imports)]
use rand::isaac::IsaacRng;

use time::*;

fn main() {
let x: collecs::vec::Vec<uint> = Vec::new();
let y = now();
}

0 comments on commit 8780d9c

Please sign in to comment.