Skip to content

Commit 9bc2f18

Browse files
lhtbrson
authored andcommitted
rustc: Add support of warning on unused imports
Fixes issue #889
1 parent f705f68 commit 9bc2f18

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

src/comp/middle/resolve.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ tag import_state {
5050
resolving(span);
5151
resolved(option::t<def>, /* value */
5252
option::t<def>, /* type */
53-
option::t<def>); /* module */
53+
option::t<def>, /* module */
54+
/* used for reporting unused import warning */
55+
ast::ident, codemap::span);
5456
}
5557

5658
type ext_hash = hashmap<{did: def_id, ident: str, ns: namespace}, def>;
@@ -106,6 +108,7 @@ type env =
106108
mod_map: hashmap<ast::node_id, @indexed_mod>,
107109
ext_map: hashmap<def_id, [ident]>,
108110
ext_cache: ext_hash,
111+
mutable used_imports: option::t<[ast::node_id]>,
109112
mutable reported: [{ident: str, sc: scope}],
110113
mutable currently_resolving: node_id,
111114
sess: session};
@@ -127,18 +130,20 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
127130
mod_map: new_int_hash::<@indexed_mod>(),
128131
ext_map: new_def_hash::<[ident]>(),
129132
ext_cache: new_ext_hash(),
133+
mutable used_imports: none,
130134
mutable reported: [],
131135
mutable currently_resolving: -1,
132136
sess: sess};
133137
map_crate(e, crate);
134138
resolve_imports(*e);
135139
check_for_collisions(e, *crate);
136140
check_bad_exports(e);
141+
e.used_imports = some([]);
137142
resolve_names(e, crate);
143+
check_unused_imports(e);
138144
ret {def_map: e.def_map, ext_map: e.ext_map};
139145
}
140146

141-
142147
// Locate all modules and imports and index them, so that the next passes can
143148
// resolve through them.
144149
fn map_crate(e: @env, c: @ast::crate) {
@@ -239,12 +244,26 @@ fn resolve_imports(e: env) {
239244
todo(node_id, name, path, span, scopes) {
240245
resolve_import(e, local_def(node_id), name, path, span, scopes);
241246
}
242-
resolved(_, _, _) { }
247+
resolved(_, _, _, _, _) { }
243248
}
244249
};
245250
e.sess.abort_if_errors();
246251
}
247252

253+
fn check_unused_imports(e: @env) {
254+
let used = option::get(e.used_imports);
255+
e.imports.items {|k, v|
256+
alt v {
257+
resolved(val, ty, md, name, sp) {
258+
if !vec::member(k, used) {
259+
e.sess.span_warn(sp, "unused import " + name);
260+
}
261+
}
262+
_ { }
263+
}
264+
};
265+
}
266+
248267
fn resolve_names(e: @env, c: @ast::crate) {
249268
let v =
250269
@{visit_native_item: visit_native_item_with_scope,
@@ -439,7 +458,7 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
439458
if is_none(val) && is_none(typ) && is_none(md) {
440459
unresolved_err(e, sc, sp, name, "import");
441460
} else {
442-
e.imports.insert(id, resolved(val, typ, md));
461+
e.imports.insert(id, resolved(val, typ, md, name, sp));
443462
}
444463
}
445464
// This function has cleanup code at the end. Do not return without going
@@ -483,8 +502,8 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
483502
// resolved state, to avoid having it reported later as a cyclic
484503
// import
485504
alt e.imports.find(defid.node) {
486-
some(resolving(_)) {
487-
e.imports.insert(defid.node, resolved(none, none, none));
505+
some(resolving(sp)) {
506+
e.imports.insert(defid.node, resolved(none, none, none, "", sp));
488507
}
489508
_ { }
490509
}
@@ -931,7 +950,14 @@ fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
931950
}
932951
ret none;
933952
}
934-
resolved(val, typ, md) {
953+
resolved(val, typ, md, _, _) {
954+
alt e.used_imports {
955+
none. { }
956+
some(lst_) {
957+
let lst = lst_ + [defid.node];
958+
e.used_imports = option::some(lst);
959+
}
960+
}
935961
ret alt ns { ns_value. { val } ns_type. { typ } ns_module. { md } };
936962
}
937963
}
@@ -1008,15 +1034,15 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
10081034
let val = per_ns(e, info, sp, id, ns_value, dr);
10091035
let typ = per_ns(e, info, sp, id, ns_type, dr);
10101036
let md = per_ns(e, info, sp, id, ns_module, dr);
1011-
info.glob_imported_names.insert(id, resolved(val, typ, md));
1037+
info.glob_imported_names.insert(id, resolved(val, typ, md, id, sp));
10121038
}
10131039
alt info.glob_imported_names.get(id) {
10141040
todo(_, _, _, _, _) { e.sess.bug("Shouldn't've put a todo in."); }
10151041
resolving(sp) {
10161042
ret none::<def>; //circularity is okay in import globs
10171043

10181044
}
1019-
resolved(val, typ, md) {
1045+
resolved(val, typ, md, _, _) {
10201046
ret alt wanted_ns {
10211047
ns_value. { val }
10221048
ns_type. { typ }
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// error-pattern:unused import
2+
import cal = bar::c::cc;
3+
4+
mod foo {
5+
type point = {x: int, y: int};
6+
type square = {p: point, h: uint, w: uint};
7+
}
8+
9+
mod bar {
10+
mod c {
11+
import foo::point;
12+
import foo::square;
13+
fn cc(p: point) -> str { ret 2 * (p.x + p.y); }
14+
}
15+
}
16+
17+
fn main() {
18+
cal({x:3, y:9});
19+
}

0 commit comments

Comments
 (0)