diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index c647e4db262..e332a71b57c 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -392,17 +392,19 @@ pub struct ImportResolution { /// The type that this `use` directive names, if there is one. mut type_target: Option, - 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, 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, _) => { @@ -5034,9 +5061,13 @@ pub impl Resolver { Some(def) => { match def { def_ty(trait_def_id) => { - self. + let added = self. add_trait_info_if_containing_method( found_traits, trait_def_id, name); + if added { + import_resolution.state.used = + true; + } } _ => { // Continue. @@ -5069,7 +5100,7 @@ pub impl Resolver { fn add_trait_info_if_containing_method(found_traits: @DVec, trait_def_id: def_id, - name: ident) { + name: ident) -> bool { debug!("(adding trait info if containing method) trying trait %d:%d \ for method '%s'", @@ -5085,9 +5116,10 @@ pub impl Resolver { trait_def_id.node, self.session.str_of(name)); (*found_traits).push(trait_def_id); + true } Some(_) | None => { - // Continue. + false } } } @@ -5204,7 +5236,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, diff --git a/src/test/compile-fail/unused-imports-warn.rs b/src/test/compile-fail/unused-imports-warn.rs index 61503159a2f..6dcdb413f88 100644 --- a/src/test/compile-fail/unused-imports-warn.rs +++ b/src/test/compile-fail/unused-imports-warn.rs @@ -8,23 +8,39 @@ // 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 + +use core::io::ReaderUtil; //~ ERROR unused import +// Be sure that if we just bring some methods into scope that they're also +// counted as being used. +use core::io::WriterUtil; + 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); + io::stdout().write_str(~"a"); }