Skip to content

Commit 4e9b8a2

Browse files
committed
Make resolving of imports behave more sanely
An import now ignores itself when resolving its target. This gets rid of the previously existing (problematic) behaviour where the import would start looking one scope up when its name was the same as its target's first component. Closes #1114
1 parent 7ed7e7f commit 4e9b8a2

File tree

1 file changed

+57
-65
lines changed

1 file changed

+57
-65
lines changed

src/comp/middle/resolve.rs

Lines changed: 57 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ type env =
107107
ext_map: hashmap<def_id, [ident]>,
108108
ext_cache: ext_hash,
109109
mutable reported: [{ident: str, sc: scope}],
110+
mutable currently_resolving: node_id,
110111
sess: session};
111112

112113

@@ -127,6 +128,7 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
127128
ext_map: new_def_hash::<[ident]>(),
128129
ext_cache: new_ext_hash(),
129130
mutable reported: [],
131+
mutable currently_resolving: -1,
130132
sess: sess};
131133
map_crate(e, crate);
132134
resolve_imports(*e);
@@ -218,11 +220,6 @@ fn map_crate(e: @env, c: @ast::crate) {
218220
}
219221
}
220222
alt vi.node {
221-
222-
223-
224-
225-
226223
//if it really is a glob import, that is
227224
ast::view_item_import_glob(path, _) {
228225
let imp = follow_import(*e, sc, path, vi.span);
@@ -435,73 +432,62 @@ fn resolve_constr(e: @env, c: @ast::constr, sc: scopes, _v: vt<scopes>) {
435432

436433
// Import resolution
437434
fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
438-
ids: [ast::ident], sp: codemap::span, sc_in: scopes) {
435+
ids: [ast::ident], sp: codemap::span, sc: scopes) {
436+
fn register(e: env, id: node_id, sc: scopes, sp: codemap::span,
437+
name: ast::ident, lookup: block(namespace) -> option::t<def>){
438+
let val = lookup(ns_value), typ = lookup(ns_type),
439+
md = lookup(ns_module);
440+
if is_none(val) && is_none(typ) && is_none(md) {
441+
unresolved_err(e, sc, sp, name, "import");
442+
} else {
443+
e.imports.insert(id, resolved(val, typ, md));
444+
}
445+
}
446+
// This function has cleanup code at the end. Do not return without going
447+
// through that.
439448
e.imports.insert(defid.node, resolving(sp));
449+
let previously_resolving = e.currently_resolving;
450+
e.currently_resolving = defid.node;
440451
let n_idents = vec::len(ids);
441452
let end_id = ids[n_idents - 1u];
442-
// Ignore the current scope if this import would shadow itself.
443-
let sc =
444-
if str::eq(name, ids[0]) { std::list::cdr(sc_in) } else { sc_in };
445453
if n_idents == 1u {
446-
register(e, defid, sp, end_id, sc_in,
447-
lookup_in_scope(e, sc, sp, end_id, ns_value),
448-
lookup_in_scope(e, sc, sp, end_id, ns_type),
449-
lookup_in_scope(e, sc, sp, end_id, ns_module));
450-
remove_if_unresolved(e.imports, defid.node);
454+
register(e, defid.node, sc, sp, name,
455+
{|ns| lookup_in_scope(e, sc, sp, end_id, ns) });
451456
} else {
452-
let dcur =
453-
alt lookup_in_scope(e, sc, sp, ids[0], ns_module) {
454-
some(dcur) { dcur }
455-
none. {
456-
unresolved_err(e, sc, sp, ids[0], ns_name(ns_module));
457-
remove_if_unresolved(e.imports, defid.node);
458-
ret;
459-
}
460-
};
461-
let i = 1u;
462-
while true {
463-
if i == n_idents - 1u {
464-
register(e, defid, sp, end_id, sc_in,
465-
lookup_in_mod(e, dcur, sp, end_id, ns_value,
466-
outside),
467-
lookup_in_mod(e, dcur, sp, end_id, ns_type, outside),
468-
lookup_in_mod(e, dcur, sp, end_id, ns_module,
469-
outside));
470-
remove_if_unresolved(e.imports, defid.node);
471-
break;
472-
} else {
473-
dcur = alt lookup_in_mod(e, dcur, sp, ids[i], ns_module,
474-
outside) {
475-
some(dcur) { dcur }
476-
none. {
477-
unresolved_err(e, sc, sp, ids[i], ns_name(ns_module));
478-
remove_if_unresolved(e.imports, defid.node);
479-
ret;
480-
}
481-
};
482-
i += 1u;
457+
alt lookup_in_scope(e, sc, sp, ids[0], ns_module) {
458+
none. { unresolved_err(e, sc, sp, ids[0], ns_name(ns_module)); }
459+
some(dcur_) {
460+
let dcur = dcur_, i = 1u;
461+
while true {
462+
if i == n_idents - 1u {
463+
register(e, defid.node, sc, sp, name, {|ns|
464+
lookup_in_mod(e, dcur, sp, end_id, ns, outside)
465+
});
466+
break;
467+
} else {
468+
dcur = alt lookup_in_mod(e, dcur, sp, ids[i], ns_module,
469+
outside) {
470+
some(dcur) { dcur }
471+
none. {
472+
unresolved_err(e, sc, sp, ids[i], ns_name(ns_module));
473+
break;
474+
}
475+
};
476+
i += 1u;
477+
}
483478
}
479+
}
484480
}
485481
}
486-
fn register(e: env, defid: def_id, sp: span, name: ident, sc: scopes,
487-
val: option::t<def>, typ: option::t<def>,
488-
md: option::t<def>) {
489-
if is_none(val) && is_none(typ) && is_none(md) {
490-
unresolved_err(e, sc, sp, name, "import");
491-
} else { e.imports.insert(defid.node, resolved(val, typ, md)); }
492-
}
493-
fn remove_if_unresolved(imports: hashmap<ast::node_id, import_state>,
494-
node_id: ast::node_id) {
495-
496-
// If we couldn't resolve the import, don't leave it in a partially
497-
// resolved state, to avoid having it reported later as a cyclic
498-
// import
499-
if imports.contains_key(node_id) {
500-
alt imports.get(node_id) {
501-
resolving(_) { imports.remove(node_id); }
502-
_ { }
503-
}
504-
}
482+
e.currently_resolving = previously_resolving;
483+
// If we couldn't resolve the import, don't leave it in a partially
484+
// resolved state, to avoid having it reported later as a cyclic
485+
// import
486+
alt e.imports.find(defid.node) {
487+
some(resolving(_)) {
488+
e.imports.insert(defid.node, resolved(none, none, none));
489+
}
490+
_ { }
505491
}
506492
}
507493

@@ -937,7 +923,13 @@ fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
937923
resolve_import(e, local_def(node_id), name, path, span, scopes);
938924
ret lookup_import(e, defid, ns);
939925
}
940-
resolving(sp) { e.sess.span_err(sp, "cyclic import"); ret none; }
926+
resolving(sp) {
927+
// Imports are simply ignored when resolving themselves.
928+
if e.currently_resolving != defid.node {
929+
e.sess.span_err(sp, "cyclic import");
930+
}
931+
ret none;
932+
}
941933
resolved(val, typ, md) {
942934
ret alt ns { ns_value. { val } ns_type. { typ } ns_module. { md } };
943935
}

0 commit comments

Comments
 (0)