From 9f8ec427e57a7da4d935fb19148586fae0d7f3c5 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Thu, 11 Sep 2014 19:14:43 +0200 Subject: [PATCH 1/2] New lint : unused_extern_crate. #10385 --- src/librustc/lint/builtin.rs | 4 ++ src/librustc/lint/context.rs | 2 +- src/librustc/middle/resolve.rs | 65 ++++++++++++++++++- .../compile-fail/lint-unused-extern-crate.rs | 32 +++++++++ 4 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/lint-unused-extern-crate.rs diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 138947e8a873b..58440a526ee20 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -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") @@ -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, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 26ed5cbfb2cc1..a464de49b4df5 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -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); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 854b8b9ba7711..b20f230bc3c6e 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -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}; @@ -899,6 +899,7 @@ struct Resolver<'a> { emit_errors: bool, used_imports: HashSet<(NodeId, Namespace)>, + used_crates: HashSet, } struct BuildReducedGraphVisitor<'a, 'b:'a> { @@ -987,6 +988,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(), @@ -2453,7 +2455,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); } } @@ -2496,6 +2505,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)); @@ -3030,6 +3044,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. @@ -3213,7 +3235,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)); } } @@ -3492,7 +3519,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)); } } @@ -5061,7 +5093,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 => { @@ -5085,6 +5124,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)) }; @@ -5168,6 +5209,10 @@ impl<'a> Resolver<'a> { }, _ => (), } + match containing_module.def_id.get() { + Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); }, + _ => {} + } return Some(def); } @@ -5787,6 +5832,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); }, + _ => {} + } } } @@ -5859,10 +5908,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); diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs new file mode 100644 index 0000000000000..a4dfdbdaeae01 --- /dev/null +++ b/src/test/compile-fail/lint-unused-extern-crate.rs @@ -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 or the MIT license +// , 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 = Vec::new(); + let y = now(); +} From 8e61612889233e7df26067e9d1c0ec7ffbac630c Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Fri, 12 Sep 2014 11:24:09 +0200 Subject: [PATCH 2/2] Removing unused extern crates. --- src/librustc_back/lib.rs | 2 -- src/libsyntax/diagnostic.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 5db6c72975587..e48f9df75648f 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -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; diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index c026a1c97c139..78d3d86b29692 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -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;