Skip to content

Commit bdcb9d9

Browse files
cixtorgraydon
authored andcommitted
Make lookup non recursive and instead move the recursion just to
find_final_def. Use the fact that the recursion is in a simpler function to detected import loops and exit.
1 parent f3c3fc0 commit bdcb9d9

File tree

2 files changed

+90
-60
lines changed

2 files changed

+90
-60
lines changed

src/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \
405405
test/compile-fail/import.rs \
406406
test/compile-fail/import2.rs \
407407
test/compile-fail/import3.rs \
408+
test/compile-fail/import4.rs \
408409
test/compile-fail/bad-recv.rs \
409410
test/compile-fail/bad-send.rs \
410411
test/compile-fail/infinite-vec-type-recursion.rs \
@@ -485,6 +486,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
485486
import.rs \
486487
import2.rs \
487488
import3.rs \
489+
import4.rs \
488490
while-type-error.rs \
489491
), \
490492
$(wildcard test/*/*.rs test/*/*.rc))

src/comp/middle/resolve.rs

Lines changed: 88 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,20 @@ tag scope {
2525
type env = rec(list[scope] scopes,
2626
session.session sess);
2727

28-
type import_map = std.map.hashmap[ast.def_id,def_wrap];
28+
type import_map = std.map.hashmap[ast.def_id,def];
2929

3030
// A simple wrapper over defs that stores a bit more information about modules
3131
// and uses so that we can use the regular lookup_name when resolving imports.
3232
tag def_wrap {
3333
def_wrap_use(@ast.view_item);
34+
def_wrap_import(@ast.view_item);
3435
def_wrap_mod(@ast.item);
3536
def_wrap_other(def);
3637
}
3738

38-
fn unwrap_def(option.t[def_wrap] d_) -> option.t[def] {
39+
fn lookup_name(&env e, import_map index,
40+
ast.ident i) -> option.t[def] {
41+
auto d_ = lookup_name_wrapped(e, i);
3942
alt (d_) {
4043
case (none[def_wrap]) {
4144
ret none[def];
@@ -48,62 +51,93 @@ fn unwrap_def(option.t[def_wrap] d_) -> option.t[def] {
4851
ret some[def](ast.def_use(id));
4952
}
5053
}
51-
fail;
54+
}
55+
case (def_wrap_import(?it)) {
56+
alt (it.node) {
57+
case (ast.view_item_import(_, ?id)) {
58+
ret index.find(id);
59+
}
60+
}
5261
}
5362
case (def_wrap_mod(?i)) {
5463
alt (i.node) {
5564
case (ast.item_mod(_, _, ?id)) {
5665
ret some[def](ast.def_mod(id));
5766
}
5867
}
59-
fail;
6068
}
6169
case (def_wrap_other(?d)) {
6270
ret some[def](d);
6371
}
6472
}
6573
}
6674
}
67-
fail;
6875
}
6976

7077
// Follow the path of an import and return what it ultimately points to.
7178

72-
fn find_final_def(&env e, &span sp, vec[ident] idents) -> option.t[def_wrap] {
73-
auto len = _vec.len[ident](idents);
74-
auto first = idents.(0);
75-
auto d_ = lookup_name(e, none[import_map], first);
76-
if (len == 1u) {
77-
ret d_;
78-
}
79-
alt (d_) {
80-
case (none[def_wrap]) {
81-
e.sess.span_err(sp, "unresolved name: " + first);
82-
ret d_;
83-
}
84-
case (some[def_wrap](?d)) {
85-
alt (d) {
86-
case (def_wrap_mod(?i)) {
87-
auto new_idents = _vec.slice[ident](idents, 1u, len);
88-
auto tmp_e = rec(scopes = nil[scope],
89-
sess = e.sess);
90-
auto new_e = update_env_for_item(tmp_e, i);
91-
ret find_final_def(new_e, sp, new_idents);
92-
}
93-
case (def_wrap_use(?c)) {
94-
e.sess.span_err(sp, "Crate access is not implemented");
95-
}
96-
case (_) {
97-
e.sess.span_err(sp, first + " is not a module or crate");
79+
fn find_final_def(&env e, &span sp, vec[ident] idents) -> def_wrap {
80+
fn found_something(&env e, std.map.hashmap[ast.def_id, bool] pending,
81+
&span sp, vec[ident] idents, def_wrap d) -> def_wrap {
82+
alt (d) {
83+
case (def_wrap_import(?imp)) {
84+
alt (imp.node) {
85+
case (ast.view_item_import(?new_idents, ?d)) {
86+
if (pending.contains_key(d)) {
87+
e.sess.span_err(sp,
88+
"recursive import");
89+
fail;
90+
}
91+
pending.insert(d, true);
92+
auto x = inner(e, pending, sp, new_idents);
93+
ret found_something(e, pending, sp, idents, x);
94+
}
9895
}
9996
}
97+
case (_) {
98+
}
99+
}
100+
auto len = _vec.len[ident](idents);
101+
if (len == 1u) {
102+
ret d;
103+
}
104+
alt (d) {
105+
case (def_wrap_mod(?i)) {
106+
auto new_idents = _vec.slice[ident](idents, 1u, len);
107+
auto tmp_e = rec(scopes = nil[scope],
108+
sess = e.sess);
109+
auto new_e = update_env_for_item(tmp_e, i);
110+
ret inner(new_e, pending, sp, new_idents);
111+
}
112+
case (def_wrap_use(?c)) {
113+
e.sess.span_err(sp, "Crate access is not implemented");
114+
}
115+
case (_) {
116+
auto first = idents.(0);
117+
e.sess.span_err(sp, first + " is not a module or crate");
118+
}
119+
}
120+
fail;
121+
}
122+
fn inner(&env e, std.map.hashmap[ast.def_id, bool] pending,
123+
&span sp, vec[ident] idents) -> def_wrap {
124+
auto first = idents.(0);
125+
auto d_ = lookup_name_wrapped(e, first);
126+
alt (d_) {
127+
case (none[def_wrap]) {
128+
e.sess.span_err(sp, "unresolved name: " + first);
129+
fail;
130+
}
131+
case (some[def_wrap](?d)) {
132+
ret found_something(e, pending, sp, idents, d);
133+
}
100134
}
101135
}
102-
fail;
136+
auto pending = new_def_hash[bool]();
137+
ret inner(e, pending, sp, idents);
103138
}
104139

105-
fn lookup_name(&env e, option.t[import_map] index,
106-
ast.ident i) -> option.t[def_wrap] {
140+
fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[def_wrap] {
107141

108142
// log "resolving name " + i;
109143

@@ -147,33 +181,24 @@ fn lookup_name(&env e, option.t[import_map] index,
147181
ret none[def_wrap];
148182
}
149183

150-
fn found_def_view(&env e, option.t[import_map] index,
151-
@ast.view_item i) -> option.t[def_wrap] {
184+
fn found_def_view(&env e, @ast.view_item i) -> option.t[def_wrap] {
152185
alt (i.node) {
153186
case (ast.view_item_use(_, _, ?id)) {
154187
ret some[def_wrap](def_wrap_use(i));
155188
}
156189
case (ast.view_item_import(?idents,?d)) {
157-
alt (index) {
158-
case (some[import_map](?idx)) {
159-
ret idx.find(d);
160-
}
161-
case (none[import_map]) {
162-
ret find_final_def(e, i.span, idents);
163-
}
164-
}
190+
ret some[def_wrap](def_wrap_import(i));
165191
}
166192
}
167193
fail;
168194
}
169195

170-
fn check_mod(&env e, option.t[import_map] index, ast.ident i,
171-
ast._mod m) -> option.t[def_wrap] {
196+
fn check_mod(&env e, ast.ident i, ast._mod m) -> option.t[def_wrap] {
172197
alt (m.index.find(i)) {
173198
case (some[ast.mod_index_entry](?ent)) {
174199
alt (ent) {
175200
case (ast.mie_view_item(?view_item)) {
176-
ret found_def_view(e, index, view_item);
201+
ret found_def_view(e, view_item);
177202
}
178203
case (ast.mie_item(?item)) {
179204
ret found_def_item(item);
@@ -199,12 +224,11 @@ fn lookup_name(&env e, option.t[import_map] index,
199224
}
200225

201226

202-
fn in_scope(ast.ident i, env e, option.t[import_map] index,
203-
&scope s) -> option.t[def_wrap] {
227+
fn in_scope(ast.ident i, env e, &scope s) -> option.t[def_wrap] {
204228
alt (s) {
205229

206230
case (scope_crate(?c)) {
207-
ret check_mod(e, index, i, c.node.module);
231+
ret check_mod(e, i, c.node.module);
208232
}
209233

210234
case (scope_item(?it)) {
@@ -238,7 +262,7 @@ fn lookup_name(&env e, option.t[import_map] index,
238262
}
239263
}
240264
case (ast.item_mod(_, ?m, _)) {
241-
ret check_mod(e, index, i, m);
265+
ret check_mod(e, i, m);
242266
}
243267
case (_) { /* fall through */ }
244268
}
@@ -267,14 +291,14 @@ fn lookup_name(&env e, option.t[import_map] index,
267291
}
268292

269293
ret std.list.find[scope,def_wrap](e.scopes,
270-
bind in_scope(i, e, index, _));
294+
bind in_scope(i, e, _));
271295
}
272296

273297
fn fold_pat_tag(&env e, &span sp, import_map index, ident i,
274298
vec[@ast.pat] args, option.t[ast.variant_def] old_def,
275299
ann a) -> @ast.pat {
276300
auto new_def;
277-
alt (unwrap_def(lookup_name(e, some(index), i))) {
301+
alt (lookup_name(e, index, i)) {
278302
case (some[def](?d)) {
279303
alt (d) {
280304
case (ast.def_variant(?did, ?vid)) {
@@ -327,7 +351,7 @@ fn fold_expr_path(&env e, &span sp, import_map index,
327351
check (n_idents != 0u);
328352
auto id0 = p.node.idents.(0);
329353

330-
auto d_ = unwrap_def(lookup_name(e, some(index), id0));
354+
auto d_ = lookup_name(e, index, id0);
331355

332356
alt (d_) {
333357
case (some[def](_)) {
@@ -362,11 +386,15 @@ fn fold_view_item_import(&env e, &span sp,
362386
auto last_id = is.(len - 1u);
363387
auto d = find_final_def(e, sp, is);
364388
alt (d) {
365-
case (none[def_wrap]) {
366-
e.sess.span_err(sp, "unresolved name: " + last_id);
389+
case (def_wrap_mod(?m)) {
390+
alt (m.node) {
391+
case (ast.item_mod(_, _, ?id)) {
392+
index.insert(id, ast.def_mod(id));
393+
}
394+
}
367395
}
368-
case (some[def_wrap](?d2)) {
369-
index.insert(id, d2);
396+
case (def_wrap_other(?target_def)) {
397+
index.insert(id, target_def);
370398
}
371399
}
372400

@@ -387,7 +415,7 @@ fn fold_ty_path(&env e, &span sp, import_map index, ast.path p,
387415
e.sess.unimpl("resolving path ty with ty params");
388416
}
389417

390-
auto d_ = unwrap_def(lookup_name(e, some(index), p.node.idents.(0)));
418+
auto d_ = lookup_name(e, index, p.node.idents.(0));
391419

392420
alt (d_) {
393421
case (some[def](?d)) {
@@ -421,7 +449,7 @@ fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate {
421449

422450
let fold.ast_fold[env] fld = fold.new_identity_fold[env]();
423451

424-
auto import_index = new_def_hash[def_wrap]();
452+
auto import_index = new_def_hash[def]();
425453
fld = @rec( fold_pat_tag = bind fold_pat_tag(_,_,import_index,_,_,_,_),
426454
fold_expr_path = bind fold_expr_path(_,_,import_index,_,_,_),
427455
fold_view_item_import

0 commit comments

Comments
 (0)