diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 7745f8b94c2..501d675564a 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -50,7 +50,9 @@ tag import_state { resolving(span); resolved(option::t, /* value */ option::t, /* type */ - option::t); /* module */ + option::t, /* module */ + /* used for reporting unused import warning */ + ast::ident, codemap::span); } type ext_hash = hashmap<{did: def_id, ident: str, ns: namespace}, def>; @@ -106,6 +108,7 @@ type env = mod_map: hashmap, ext_map: hashmap, ext_cache: ext_hash, + mutable used_imports: option::t<[ast::node_id]>, mutable reported: [{ident: str, sc: scope}], mutable currently_resolving: node_id, sess: session}; @@ -127,6 +130,7 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) -> mod_map: new_int_hash::<@indexed_mod>(), ext_map: new_def_hash::<[ident]>(), ext_cache: new_ext_hash(), + mutable used_imports: none, mutable reported: [], mutable currently_resolving: -1, sess: sess}; @@ -134,11 +138,12 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) -> resolve_imports(*e); check_for_collisions(e, *crate); check_bad_exports(e); + e.used_imports = some([]); resolve_names(e, crate); + check_unused_imports(e); ret {def_map: e.def_map, ext_map: e.ext_map}; } - // Locate all modules and imports and index them, so that the next passes can // resolve through them. fn map_crate(e: @env, c: @ast::crate) { @@ -239,12 +244,26 @@ fn resolve_imports(e: env) { todo(node_id, name, path, span, scopes) { resolve_import(e, local_def(node_id), name, path, span, scopes); } - resolved(_, _, _) { } + resolved(_, _, _, _, _) { } } }; e.sess.abort_if_errors(); } +fn check_unused_imports(e: @env) { + let used = option::get(e.used_imports); + e.imports.items {|k, v| + alt v { + resolved(val, ty, md, name, sp) { + if !vec::member(k, used) { + e.sess.span_warn(sp, "unused import " + name); + } + } + _ { } + } + }; +} + fn resolve_names(e: @env, c: @ast::crate) { let v = @{visit_native_item: visit_native_item_with_scope, @@ -439,7 +458,7 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident, if is_none(val) && is_none(typ) && is_none(md) { unresolved_err(e, sc, sp, name, "import"); } else { - e.imports.insert(id, resolved(val, typ, md)); + e.imports.insert(id, resolved(val, typ, md, name, sp)); } } // 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, // resolved state, to avoid having it reported later as a cyclic // import alt e.imports.find(defid.node) { - some(resolving(_)) { - e.imports.insert(defid.node, resolved(none, none, none)); + some(resolving(sp)) { + e.imports.insert(defid.node, resolved(none, none, none, "", sp)); } _ { } } @@ -931,7 +950,14 @@ fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t { } ret none; } - resolved(val, typ, md) { + resolved(val, typ, md, _, _) { + alt e.used_imports { + none. { } + some(lst_) { + let lst = lst_ + [defid.node]; + e.used_imports = option::some(lst); + } + } ret alt ns { ns_value. { val } ns_type. { typ } ns_module. { md } }; } } @@ -1008,7 +1034,7 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident, let val = per_ns(e, info, sp, id, ns_value, dr); let typ = per_ns(e, info, sp, id, ns_type, dr); let md = per_ns(e, info, sp, id, ns_module, dr); - info.glob_imported_names.insert(id, resolved(val, typ, md)); + info.glob_imported_names.insert(id, resolved(val, typ, md, id, sp)); } alt info.glob_imported_names.get(id) { todo(_, _, _, _, _) { e.sess.bug("Shouldn't've put a todo in."); } @@ -1016,7 +1042,7 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident, ret none::; //circularity is okay in import globs } - resolved(val, typ, md) { + resolved(val, typ, md, _, _) { ret alt wanted_ns { ns_value. { val } ns_type. { typ } diff --git a/src/test/compile-fail/unused-imports-warn.rs b/src/test/compile-fail/unused-imports-warn.rs new file mode 100644 index 00000000000..88e42e0490a --- /dev/null +++ b/src/test/compile-fail/unused-imports-warn.rs @@ -0,0 +1,19 @@ +// error-pattern:unused import +import cal = bar::c::cc; + +mod foo { + type point = {x: int, y: int}; + type square = {p: point, h: uint, w: uint}; +} + +mod bar { + mod c { + import foo::point; + import foo::square; + fn cc(p: point) -> str { ret 2 * (p.x + p.y); } + } +} + +fn main() { + cal({x:3, y:9}); +}