Skip to content

Commit 2bc9655

Browse files
committed
auto merge of #4803 : alexcrichton/rust/fix-unused-imports, r=graydon
The first commit message has most of the comments, but this pull request basically fixes a lot of issues surrounding the `unused_imports` warning/deny attribute. Before this patch there were these problems: 1. Unused imports from `prelude.rs` were warned about with dummy spans, leading to a large number of confusing warnings. 2. Unused imports from `intrinsic.rs` were warned about with the file `<intrinsic>` which couldn't be forced to go away 3. Methods used from imported traites (like `io::WriterUtil`) resulted in an unused warning of the import even though it was used. 4. If one `use` statement imported N modules, M of which weren't used, M warning statements were issued. 5. If a glob import statement was used, each public export of the target module which wasn't used had a warning issued. This patch deals with all these cases by doing: 1. Ignore unused imports from `prelude.rs` (indicated by a dummy span of 0) 2. Ignore unused imports from `intrinsic.rs` (test on the imported module name, is there a better way?) 3. Track when imported modules are used as candidates for methods, and just assume they're used. This may not end up being the actual case, but in theory not warning about an unused thing is worse than warning about a used thing. 4. Only issue one warning statement 5. Only issue one warning statement. This is the first time I've edited the compiler itself, and I tried to keep up with the style around, but I may have missed something here or there...
2 parents 4272765 + b368cb2 commit 2bc9655

File tree

2 files changed

+82
-28
lines changed

2 files changed

+82
-28
lines changed

src/librustc/middle/resolve.rs

+58-20
Original file line numberDiff line numberDiff line change
@@ -392,17 +392,19 @@ pub struct ImportResolution {
392392
/// The type that this `use` directive names, if there is one.
393393
mut type_target: Option<Target>,
394394
395-
mut used: bool,
395+
/// There exists one state per import statement
396+
state: @mut ImportState,
396397
}
397398
398-
pub fn ImportResolution(privacy: Privacy, span: span) -> ImportResolution {
399+
pub fn ImportResolution(privacy: Privacy, span: span,
400+
state: @mut ImportState) -> ImportResolution {
399401
ImportResolution {
400402
privacy: privacy,
401403
span: span,
402404
outstanding_references: 0,
403405
value_target: None,
404406
type_target: None,
405-
used: false
407+
state: state,
406408
}
407409
}
408410
@@ -415,6 +417,15 @@ pub impl ImportResolution {
415417
}
416418
}
417419
420+
pub struct ImportState {
421+
used: bool,
422+
warned: bool
423+
}
424+
425+
pub fn ImportState() -> ImportState {
426+
ImportState{ used: false, warned: false }
427+
}
428+
418429
/// The link from a module up to its nearest parent node.
419430
pub enum ParentLink {
420431
NoParentLink,
@@ -1415,6 +1426,7 @@ pub impl Resolver {
14151426
14161427
// Build up the import directives.
14171428
let module_ = self.get_module_from_parent(parent);
1429+
let state = @mut ImportState();
14181430
match view_path.node {
14191431
view_path_simple(binding, full_path, ns, _) => {
14201432
let ns = match ns {
@@ -1430,7 +1442,8 @@ pub impl Resolver {
14301442
module_,
14311443
module_path,
14321444
subclass,
1433-
view_path.span);
1445+
view_path.span,
1446+
state);
14341447
}
14351448
view_path_list(_, ref source_idents, _) => {
14361449
for (*source_idents).each |source_ident| {
@@ -1442,15 +1455,17 @@ pub impl Resolver {
14421455
module_,
14431456
module_path,
14441457
subclass,
1445-
view_path.span);
1458+
view_path.span,
1459+
state);
14461460
}
14471461
}
14481462
view_path_glob(_, _) => {
14491463
self.build_import_directive(privacy,
14501464
module_,
14511465
module_path,
14521466
@GlobImport,
1453-
view_path.span);
1467+
view_path.span,
1468+
state);
14541469
}
14551470
}
14561471
}
@@ -1573,7 +1588,8 @@ pub impl Resolver {
15731588
// avoid creating cycles in the
15741589
// module graph.
15751590
1576-
let resolution = @ImportResolution(Public, dummy_sp());
1591+
let resolution = @ImportResolution(Public, dummy_sp(),
1592+
@mut ImportState());
15771593
resolution.outstanding_references = 0;
15781594
15791595
match existing_module.parent_link {
@@ -1826,7 +1842,8 @@ pub impl Resolver {
18261842
module_: @Module,
18271843
module_path: @DVec<ident>,
18281844
subclass: @ImportDirectiveSubclass,
1829-
span: span) {
1845+
span: span,
1846+
state: @mut ImportState) {
18301847
let directive = @ImportDirective(privacy, module_path,
18311848
subclass, span);
18321849
module_.imports.push(directive);
@@ -1850,7 +1867,14 @@ pub impl Resolver {
18501867
}
18511868
None => {
18521869
debug!("(building import directive) creating new");
1853-
let resolution = @ImportResolution(privacy, span);
1870+
let resolution = @ImportResolution(privacy, span,
1871+
state);
1872+
let name = self.idents_to_str(module_path.get());
1873+
// Don't warn about unused intrinsics because they're
1874+
// automatically appended to all files
1875+
if name == ~"intrinsic::rusti" {
1876+
resolution.state.warned = true;
1877+
}
18541878
resolution.outstanding_references = 1;
18551879
module_.import_resolutions.insert(target, resolution);
18561880
}
@@ -2183,7 +2207,7 @@ pub impl Resolver {
21832207
return UnboundResult;
21842208
}
21852209
Some(target) => {
2186-
import_resolution.used = true;
2210+
import_resolution.state.used = true;
21872211
return BoundResult(target.target_module,
21882212
target.bindings);
21892213
}
@@ -2352,7 +2376,7 @@ pub impl Resolver {
23522376
module_result = UnboundResult;
23532377
}
23542378
Some(target) => {
2355-
import_resolution.used = true;
2379+
import_resolution.state.used = true;
23562380
module_result = BoundResult
23572381
(target.target_module,
23582382
target.bindings);
@@ -2419,6 +2443,7 @@ pub impl Resolver {
24192443
// everything it can to the list of import resolutions of the module
24202444
// node.
24212445
debug!("(resolving glob import) resolving %? glob import", privacy);
2446+
let state = @mut ImportState();
24222447
24232448
// We must bail out if the node has unresolved imports of any kind
24242449
// (including globs).
@@ -2445,7 +2470,8 @@ pub impl Resolver {
24452470
// Simple: just copy the old import resolution.
24462471
let new_import_resolution =
24472472
@ImportResolution(privacy,
2448-
target_import_resolution.span);
2473+
target_import_resolution.span,
2474+
state);
24492475
new_import_resolution.value_target =
24502476
copy target_import_resolution.value_target;
24512477
new_import_resolution.type_target =
@@ -2486,7 +2512,8 @@ pub impl Resolver {
24862512
match module_.import_resolutions.find(&ident) {
24872513
None => {
24882514
// Create a new import resolution from this child.
2489-
dest_import_resolution = @ImportResolution(privacy, span);
2515+
dest_import_resolution = @ImportResolution(privacy, span,
2516+
state);
24902517
module_.import_resolutions.insert
24912518
(ident, dest_import_resolution);
24922519
}
@@ -2713,7 +2740,7 @@ pub impl Resolver {
27132740
namespace);
27142741
}
27152742
Some(target) => {
2716-
import_resolution.used = true;
2743+
import_resolution.state.used = true;
27172744
return Success(copy target);
27182745
}
27192746
}
@@ -2962,7 +2989,7 @@ pub impl Resolver {
29622989
Some(target) => {
29632990
debug!("(resolving name in module) resolved to \
29642991
import");
2965-
import_resolution.used = true;
2992+
import_resolution.state.used = true;
29662993
return Success(copy target);
29672994
}
29682995
}
@@ -4560,7 +4587,7 @@ pub impl Resolver {
45604587
namespace)) {
45614588
(Some(def), Some(Public)) => {
45624589
// Found it.
4563-
import_resolution.used = true;
4590+
import_resolution.state.used = true;
45644591
return ImportNameDefinition(def);
45654592
}
45664593
(Some(_), _) | (None, _) => {
@@ -5034,9 +5061,13 @@ pub impl Resolver {
50345061
Some(def) => {
50355062
match def {
50365063
def_ty(trait_def_id) => {
5037-
self.
5064+
let added = self.
50385065
add_trait_info_if_containing_method(
50395066
found_traits, trait_def_id, name);
5067+
if added {
5068+
import_resolution.state.used =
5069+
true;
5070+
}
50405071
}
50415072
_ => {
50425073
// Continue.
@@ -5069,7 +5100,7 @@ pub impl Resolver {
50695100

50705101
fn add_trait_info_if_containing_method(found_traits: @DVec<def_id>,
50715102
trait_def_id: def_id,
5072-
name: ident) {
5103+
name: ident) -> bool {
50735104

50745105
debug!("(adding trait info if containing method) trying trait %d:%d \
50755106
for method '%s'",
@@ -5085,9 +5116,10 @@ pub impl Resolver {
50855116
trait_def_id.node,
50865117
self.session.str_of(name));
50875118
(*found_traits).push(trait_def_id);
5119+
true
50885120
}
50895121
Some(_) | None => {
5090-
// Continue.
5122+
false
50915123
}
50925124
}
50935125
}
@@ -5204,7 +5236,13 @@ pub impl Resolver {
52045236

52055237
fn check_for_unused_imports_in_module(module_: @Module) {
52065238
for module_.import_resolutions.each_value_ref |&import_resolution| {
5207-
if !import_resolution.used {
5239+
// Ignore dummy spans for things like automatically injected
5240+
// imports for the prelude, and also don't warn about the same
5241+
// import statement being unused more than once.
5242+
if !import_resolution.state.used &&
5243+
!import_resolution.state.warned &&
5244+
import_resolution.span != dummy_sp() {
5245+
import_resolution.state.warned = true;
52085246
match self.unused_import_lint_level {
52095247
warn => {
52105248
self.session.span_warn(import_resolution.span,

src/test/compile-fail/unused-imports-warn.rs

+24-8
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,39 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern:unused import
12-
// compile-flags:-W unused-imports
11+
// compile-flags: -D unused-imports
12+
1313
use cal = bar::c::cc;
1414

15+
use core::either::Right; //~ ERROR unused import
16+
17+
use core::util::*; // shouldn't get errors for not using
18+
// everything imported
19+
20+
// Should only get one error instead of two errors here
21+
use core::option::{Some, None}; //~ ERROR unused import
22+
23+
use core::io::ReaderUtil; //~ ERROR unused import
24+
// Be sure that if we just bring some methods into scope that they're also
25+
// counted as being used.
26+
use core::io::WriterUtil;
27+
1528
mod foo {
16-
pub type point = {x: int, y: int};
17-
pub type square = {p: point, h: uint, w: uint};
29+
pub struct Point{x: int, y: int}
30+
pub struct Square{p: Point, h: uint, w: uint}
1831
}
1932

2033
mod bar {
2134
pub mod c {
22-
use foo::point;
23-
use foo::square;
24-
pub fn cc(p: point) -> str { return 2 * (p.x + p.y); }
35+
use foo::Point;
36+
use foo::Square; //~ ERROR unused import
37+
pub fn cc(p: Point) -> int { return 2 * (p.x + p.y); }
2538
}
2639
}
2740

2841
fn main() {
29-
cal({x:3, y:9});
42+
cal(foo::Point{x:3, y:9});
43+
let a = 3;
44+
ignore(a);
45+
io::stdout().write_str(~"a");
3046
}

0 commit comments

Comments
 (0)