Fix some bugs with -W unused-imports

1. Don't warn about anything not used in the prelude which is autmoatically
   injected, accomplished with a test that the span is equal to a dummy span.
2. Don't warn about unused imports from the injected intrinsic module,
   accomplished by testing against the name of the imported module
3. If anything is used from a glob import, don't warn about the glob import.
4. If an import imports more than one thing, and none of them are used, only
   issue a warning once

Also updated the unused-imports-warn test to have stricter requirements on
error messages.
This commit is contained in:
Alex Crichton 2013-02-05 02:01:02 -05:00
parent f1b05ece93
commit 6a4483ec7a
2 changed files with 68 additions and 25 deletions

View file

@ -392,17 +392,19 @@ pub struct ImportResolution {
/// The type that this `use` directive names, if there is one.
mut type_target: Option<Target>,
mut used: bool,
/// There exists one state per import statement
state: @mut ImportState,
}
pub fn ImportResolution(privacy: Privacy, span: span) -> ImportResolution {
pub fn ImportResolution(privacy: Privacy, span: span,
state: @mut ImportState) -> ImportResolution {
ImportResolution {
privacy: privacy,
span: span,
outstanding_references: 0,
value_target: None,
type_target: None,
used: false
state: state,
}
}
@ -415,6 +417,15 @@ pub impl ImportResolution {
}
}
pub struct ImportState {
used: bool,
warned: bool
}
pub fn ImportState() -> ImportState {
ImportState{ used: false, warned: false }
}
/// The link from a module up to its nearest parent node.
pub enum ParentLink {
NoParentLink,
@ -1415,6 +1426,7 @@ pub impl Resolver {
// Build up the import directives.
let module_ = self.get_module_from_parent(parent);
let state = @mut ImportState();
match view_path.node {
view_path_simple(binding, full_path, ns, _) => {
let ns = match ns {
@ -1430,7 +1442,8 @@ pub impl Resolver {
module_,
module_path,
subclass,
view_path.span);
view_path.span,
state);
}
view_path_list(_, ref source_idents, _) => {
for (*source_idents).each |source_ident| {
@ -1442,7 +1455,8 @@ pub impl Resolver {
module_,
module_path,
subclass,
view_path.span);
view_path.span,
state);
}
}
view_path_glob(_, _) => {
@ -1450,7 +1464,8 @@ pub impl Resolver {
module_,
module_path,
@GlobImport,
view_path.span);
view_path.span,
state);
}
}
}
@ -1573,7 +1588,8 @@ pub impl Resolver {
// avoid creating cycles in the
// module graph.
let resolution = @ImportResolution(Public, dummy_sp());
let resolution = @ImportResolution(Public, dummy_sp(),
@mut ImportState());
resolution.outstanding_references = 0;
match existing_module.parent_link {
@ -1826,7 +1842,8 @@ pub impl Resolver {
module_: @Module,
module_path: @DVec<ident>,
subclass: @ImportDirectiveSubclass,
span: span) {
span: span,
state: @mut ImportState) {
let directive = @ImportDirective(privacy, module_path,
subclass, span);
module_.imports.push(directive);
@ -1850,7 +1867,14 @@ pub impl Resolver {
}
None => {
debug!("(building import directive) creating new");
let resolution = @ImportResolution(privacy, span);
let resolution = @ImportResolution(privacy, span,
state);
let name = self.idents_to_str(module_path.get());
// Don't warn about unused intrinsics because they're
// automatically appended to all files
if name == ~"intrinsic::rusti" {
resolution.state.warned = true;
}
resolution.outstanding_references = 1;
module_.import_resolutions.insert(target, resolution);
}
@ -2183,7 +2207,7 @@ pub impl Resolver {
return UnboundResult;
}
Some(target) => {
import_resolution.used = true;
import_resolution.state.used = true;
return BoundResult(target.target_module,
target.bindings);
}
@ -2352,7 +2376,7 @@ pub impl Resolver {
module_result = UnboundResult;
}
Some(target) => {
import_resolution.used = true;
import_resolution.state.used = true;
module_result = BoundResult
(target.target_module,
target.bindings);
@ -2419,6 +2443,7 @@ pub impl Resolver {
// everything it can to the list of import resolutions of the module
// node.
debug!("(resolving glob import) resolving %? glob import", privacy);
let state = @mut ImportState();
// We must bail out if the node has unresolved imports of any kind
// (including globs).
@ -2445,7 +2470,8 @@ pub impl Resolver {
// Simple: just copy the old import resolution.
let new_import_resolution =
@ImportResolution(privacy,
target_import_resolution.span);
target_import_resolution.span,
state);
new_import_resolution.value_target =
copy target_import_resolution.value_target;
new_import_resolution.type_target =
@ -2486,7 +2512,8 @@ pub impl Resolver {
match module_.import_resolutions.find(&ident) {
None => {
// Create a new import resolution from this child.
dest_import_resolution = @ImportResolution(privacy, span);
dest_import_resolution = @ImportResolution(privacy, span,
state);
module_.import_resolutions.insert
(ident, dest_import_resolution);
}
@ -2713,7 +2740,7 @@ pub impl Resolver {
namespace);
}
Some(target) => {
import_resolution.used = true;
import_resolution.state.used = true;
return Success(copy target);
}
}
@ -2962,7 +2989,7 @@ pub impl Resolver {
Some(target) => {
debug!("(resolving name in module) resolved to \
import");
import_resolution.used = true;
import_resolution.state.used = true;
return Success(copy target);
}
}
@ -4560,7 +4587,7 @@ pub impl Resolver {
namespace)) {
(Some(def), Some(Public)) => {
// Found it.
import_resolution.used = true;
import_resolution.state.used = true;
return ImportNameDefinition(def);
}
(Some(_), _) | (None, _) => {
@ -5204,7 +5231,13 @@ pub impl Resolver {
fn check_for_unused_imports_in_module(module_: @Module) {
for module_.import_resolutions.each_value_ref |&import_resolution| {
if !import_resolution.used {
// Ignore dummy spans for things like automatically injected
// imports for the prelude, and also don't warn about the same
// import statement being unused more than once.
if !import_resolution.state.used &&
!import_resolution.state.warned &&
import_resolution.span != dummy_sp() {
import_resolution.state.warned = true;
match self.unused_import_lint_level {
warn => {
self.session.span_warn(import_resolution.span,

View file

@ -8,23 +8,33 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:unused import
// compile-flags:-W unused-imports
// compile-flags: -D unused-imports
use cal = bar::c::cc;
use core::either::Right; //~ ERROR unused import
use core::util::*; // shouldn't get errors for not using
// everything imported
// Should only get one error instead of two errors here
use core::option::{Some, None}; //~ ERROR unused import
mod foo {
pub type point = {x: int, y: int};
pub type square = {p: point, h: uint, w: uint};
pub struct Point{x: int, y: int}
pub struct Square{p: Point, h: uint, w: uint}
}
mod bar {
pub mod c {
use foo::point;
use foo::square;
pub fn cc(p: point) -> str { return 2 * (p.x + p.y); }
use foo::Point;
use foo::Square; //~ ERROR unused import
pub fn cc(p: Point) -> int { return 2 * (p.x + p.y); }
}
}
fn main() {
cal({x:3, y:9});
cal(foo::Point{x:3, y:9});
let a = 3;
ignore(a);
}