Skip to content

Commit 5864d4e

Browse files
committed
Report unresolved names only once per function
Closes #708
1 parent bc33897 commit 5864d4e

File tree

1 file changed

+52
-32
lines changed

1 file changed

+52
-32
lines changed

src/comp/middle/resolve.rs

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import std::list::list;
2727
import std::list::nil;
2828
import std::list::cons;
2929
import std::option;
30+
import std::option::is_none;
3031
import std::option::some;
3132
import std::option::none;
3233
import std::str;
@@ -89,7 +90,6 @@ tag mod_index_entry {
8990
mie_item(@ast::item);
9091
mie_native_item(@ast::native_item);
9192
mie_tag_variant(@ast::item /* tag item */, uint /* variant index */);
92-
9393
}
9494

9595
type mod_index = hashmap[ident, list[mod_index_entry]];
@@ -117,6 +117,7 @@ type env =
117117
hashmap[ast::node_id, @indexed_mod] mod_map,
118118
hashmap[def_id, ident[]] ext_map,
119119
ext_hash ext_cache,
120+
mutable tup(str, scope)[] reported,
120121
session sess);
121122

122123

@@ -136,6 +137,7 @@ fn resolve_crate(session sess, &ast_map::map amap, @ast::crate crate)
136137
mod_map=new_int_hash[@indexed_mod](),
137138
ext_map=new_def_hash[ident[]](),
138139
ext_cache=new_ext_hash(),
140+
mutable reported=~[],
139141
sess=sess);
140142
map_crate(e, crate);
141143
resolve_imports(*e);
@@ -386,7 +388,7 @@ fn follow_import(&env e, &scopes sc, &ident[] path, &span sp)
386388
auto i = 1u;
387389
while (true && option::is_some(dcur)) {
388390
if (i == path_len) { break; }
389-
dcur = lookup_in_mod_strict(e, option::get(dcur),
391+
dcur = lookup_in_mod_strict(e, sc, option::get(dcur),
390392
sp, path.(i), ns_module, outside);
391393
i += 1u;
392394
}
@@ -424,7 +426,7 @@ fn resolve_constr(@env e, node_id id, &@ast::constr c, &scopes sc,
424426
}
425427

426428
// Import resolution
427-
fn resolve_import(&env e, &@ast::view_item it, scopes sc) {
429+
fn resolve_import(&env e, &@ast::view_item it, &scopes sc_in) {
428430
auto defid;
429431
auto ids;
430432
auto name;
@@ -439,11 +441,10 @@ fn resolve_import(&env e, &@ast::view_item it, scopes sc) {
439441
auto n_idents = ivec::len(ids);
440442
auto end_id = ids.(n_idents - 1u);
441443
// Ignore the current scope if this import would shadow itself.
442-
if (str::eq(name, ids.(0))) {
443-
sc = std::list::cdr(sc);
444-
}
444+
auto sc = if str::eq(name, ids.(0)) { std::list::cdr(sc_in) }
445+
else { sc_in };
445446
if (n_idents == 1u) {
446-
register(e, defid, it.span, end_id,
447+
register(e, defid, it.span, end_id, sc_in,
447448
lookup_in_scope(e, sc, it.span, end_id, ns_value),
448449
lookup_in_scope(e, sc, it.span, end_id, ns_type),
449450
lookup_in_scope(e, sc, it.span, end_id, ns_module));
@@ -454,15 +455,15 @@ fn resolve_import(&env e, &@ast::view_item it, scopes sc) {
454455
dcur
455456
}
456457
case (none) {
457-
unresolved_err(e, it.span, ids.(0), ns_name(ns_module));
458+
unresolved_err(e, sc, it.span, ids.(0), ns_name(ns_module));
458459
remove_if_unresolved(e.imports, defid._1);
459460
ret () // FIXME (issue #521)
460461
}
461462
};
462463
auto i = 1u;
463464
while (true) {
464465
if (i == n_idents - 1u) {
465-
register(e, defid, it.span, end_id,
466+
register(e, defid, it.span, end_id, sc_in,
466467
lookup_in_mod(e, dcur, it.span, end_id, ns_value,
467468
outside),
468469
lookup_in_mod(e, dcur, it.span, end_id, ns_type,
@@ -478,7 +479,7 @@ fn resolve_import(&env e, &@ast::view_item it, scopes sc) {
478479
dcur
479480
}
480481
case (none) {
481-
unresolved_err(e, it.span, ids.(i),
482+
unresolved_err(e, sc, it.span, ids.(i),
482483
ns_name(ns_module));
483484
remove_if_unresolved(e.imports, defid._1);
484485
ret () // FIXME (issue #521)
@@ -488,12 +489,11 @@ fn resolve_import(&env e, &@ast::view_item it, scopes sc) {
488489
}
489490
}
490491
}
491-
fn register(&env e, def_id defid, &span sp, &ident name,
492+
fn register(&env e, def_id defid, &span sp, &ident name, &scopes sc,
492493
&option::t[def] val, &option::t[def] typ,
493494
&option::t[def] md) {
494-
if (option::is_none(val) && option::is_none(typ) &&
495-
option::is_none(md)) {
496-
unresolved_err(e, sp, name, "import");
495+
if is_none(val) && is_none(typ) && is_none(md) {
496+
unresolved_err(e, sc, sp, name, "import");
497497
} else {
498498
e.imports.insert(defid._1, resolved(val, typ, md));
499499
}
@@ -524,7 +524,28 @@ fn ns_name(namespace ns) -> str {
524524
}
525525
}
526526

527-
fn unresolved_err(&env e, &span sp, &ident name, &str kind) {
527+
fn unresolved_err(&env e, &scopes sc, &span sp, &ident name, &str kind) {
528+
fn find_fn_or_mod_scope(scopes sc) -> scope {
529+
while true {
530+
alt sc {
531+
cons(?cur, ?rest) {
532+
alt cur {
533+
scope_crate | scope_fn(_, _) |
534+
scope_item(@{node: ast::item_mod(_), _}) {
535+
ret cur;
536+
}
537+
_ { sc = *rest; }
538+
}
539+
}
540+
}
541+
}
542+
fail;
543+
}
544+
auto err_scope = find_fn_or_mod_scope(sc);
545+
for (tup(str, scope) rs in e.reported) {
546+
if str::eq(rs._0, name) && err_scope == rs._1 { ret; }
547+
}
548+
e.reported += ~[tup(name, err_scope)];
528549
e.sess.span_err(sp, mk_unresolved_msg(name, kind));
529550
}
530551

@@ -555,7 +576,7 @@ fn lookup_path_strict(&env e, &scopes sc, &span sp, &ast::path_ pth,
555576
auto i = 1u;
556577
while (i < n_idents && option::is_some(dcur)) {
557578
auto curns = if (n_idents == i + 1u) { ns } else { ns_module };
558-
dcur = lookup_in_mod_strict(e, option::get(dcur),
579+
dcur = lookup_in_mod_strict(e, sc, option::get(dcur),
559580
sp, pth.idents.(i), curns, outside);
560581
i += 1u;
561582
}
@@ -566,7 +587,7 @@ fn lookup_in_scope_strict(&env e, scopes sc, &span sp, &ident name,
566587
namespace ns) -> option::t[def] {
567588
alt (lookup_in_scope(e, sc, sp, name, ns)) {
568589
case (none) {
569-
unresolved_err(e, sp, name, ns_name(ns));
590+
unresolved_err(e, sc, sp, name, ns_name(ns));
570591
ret none;
571592
}
572593
case (some(?d)) { ret some(d); }
@@ -662,7 +683,7 @@ fn lookup_in_scope(&env e, scopes sc, &span sp, &ident name, namespace ns) ->
662683
case (nil) { ret none[def]; }
663684
case (cons(?hd, ?tl)) {
664685
auto fnd = in_scope(e, sp, name, hd, ns);
665-
if (!option::is_none(fnd)) {
686+
if (!is_none(fnd)) {
666687
auto df = option::get(fnd);
667688
if (left_fn && def_is_local(df) ||
668689
left_fn_level2 && def_is_obj_field(df)
@@ -713,13 +734,13 @@ fn lookup_in_pat(&ident name, &ast::pat pat) -> option::t[def] {
713734
case (ast::pat_tag(_, ?pats)) {
714735
for (@ast::pat p in pats) {
715736
auto found = lookup_in_pat(name, *p);
716-
if (!option::is_none(found)) { ret found; }
737+
if (!is_none(found)) { ret found; }
717738
}
718739
}
719740
case (ast::pat_rec(?fields, _)) {
720741
for (ast::field_pat f in fields) {
721742
auto found = lookup_in_pat(name, *f.pat);
722-
if (!option::is_none(found)) { ret found; }
743+
if (!is_none(found)) { ret found; }
723744
}
724745
}
725746
case (ast::pat_box(?inner)) { ret lookup_in_pat(name, *inner); }
@@ -793,7 +814,7 @@ fn lookup_in_block(&ident name, &ast::block_ b, namespace ns) ->
793814
case (_) {
794815
if (str::eq(it.ident, name)) {
795816
auto found = found_def_item(it, ns);
796-
if (!option::is_none(found)) {
817+
if (!is_none(found)) {
797818
ret found;
798819
}
799820
}
@@ -861,11 +882,11 @@ fn found_def_item(&@ast::item i, namespace ns) -> option::t[def] {
861882
ret none[def];
862883
}
863884

864-
fn lookup_in_mod_strict(&env e, def m, &span sp, &ident name, namespace ns,
865-
dir dr) -> option::t[def] {
885+
fn lookup_in_mod_strict(&env e, &scopes sc, def m, &span sp, &ident name,
886+
namespace ns, dir dr) -> option::t[def] {
866887
alt (lookup_in_mod(e, m, sp, name, ns, dr)) {
867888
case (none) {
868-
unresolved_err(e, sp, name, ns_name(ns));
889+
unresolved_err(e, sc, sp, name, ns_name(ns));
869890
ret none;
870891
}
871892
case (some(?d)) { ret some(d); }
@@ -879,11 +900,11 @@ fn lookup_in_mod(&env e, &def m, &span sp, &ident name, namespace ns,
879900
// examining a module in an external crate
880901

881902
auto cached = e.ext_cache.find(tup(defid, name, ns));
882-
if (!option::is_none(cached)) { ret cached; }
903+
if (!is_none(cached)) { ret cached; }
883904
auto path = ~[name];
884905
if (defid._1 != -1) { path = e.ext_map.get(defid) + path; }
885906
auto fnd = lookup_external(e, defid._0, path, ns);
886-
if (!option::is_none(fnd)) {
907+
if (!is_none(fnd)) {
887908
e.ext_cache.insert(tup(defid, name, ns), option::get(fnd));
888909
}
889910
ret fnd;
@@ -958,7 +979,7 @@ fn lookup_in_local_mod(&env e, node_id node_id, &span sp, &ident id,
958979
case (nil) { break; }
959980
case (cons(?hd, ?tl)) {
960981
auto found = lookup_in_mie(e, hd, ns);
961-
if (!option::is_none(found)) { ret found; }
982+
if (!is_none(found)) { ret found; }
962983
lst = *tl;
963984
}
964985
}
@@ -1196,17 +1217,17 @@ fn check_mod_name(&env e, &ident name, list[mod_index_entry] entries) {
11961217
while (true) {
11971218
alt (entries) {
11981219
case (cons(?entry, ?rest)) {
1199-
if (!option::is_none(lookup_in_mie(e, entry, ns_value))) {
1220+
if (!is_none(lookup_in_mie(e, entry, ns_value))) {
12001221
if (saw_value) {
12011222
dup(e, mie_span(entry), "", name);
12021223
} else { saw_value = true; }
12031224
}
1204-
if (!option::is_none(lookup_in_mie(e, entry, ns_type))) {
1225+
if (!is_none(lookup_in_mie(e, entry, ns_type))) {
12051226
if (saw_type) {
12061227
dup(e, mie_span(entry), "type ", name);
12071228
} else { saw_type = true; }
12081229
}
1209-
if (!option::is_none(lookup_in_mie(e, entry, ns_module))) {
1230+
if (!is_none(lookup_in_mie(e, entry, ns_module))) {
12101231
if (saw_mod) {
12111232
dup(e, mie_span(entry), "module ", name);
12121233
} else { saw_mod = true; }
@@ -1283,8 +1304,7 @@ fn check_arm(@env e, &ast::arm a, &() x, &vt[()] v) {
12831304
"inconsistent number of bindings");
12841305
} else {
12851306
for (ident name in ch.seen) {
1286-
if (option::is_none(ivec::find(bind str::eq(name, _),
1287-
seen0))) {
1307+
if (is_none(ivec::find(bind str::eq(name, _), seen0))) {
12881308
// Fight the alias checker
12891309
auto name_ = name;
12901310
e.sess.span_err

0 commit comments

Comments
 (0)