Skip to content

Commit 54ca856

Browse files
paulstansifergraydon
authored andcommitted
Fix bugs: make sure glob imports show up in the right module,
and make sure that circular glob imports don't diverge.
1 parent 3375b8f commit 54ca856

File tree

6 files changed

+178
-70
lines changed

6 files changed

+178
-70
lines changed

src/comp/middle/resolve.rs

Lines changed: 92 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import util::common::new_str_hash;
1212
import util::common::span;
1313
import middle::tstate::ann::ts_ann;
1414
import std::map::hashmap;
15+
import std::list;
1516
import std::list::list;
1617
import std::list::nil;
1718
import std::list::cons;
@@ -168,40 +169,43 @@ fn map_crate(&@env e, &ast::crate c) {
168169
}
169170

170171
// Next, assemble the links for globbed imports.
171-
172-
let @indexed_mod cur_mod = e.mod_map.get(-1);
173-
174172
cell = @mutable nil[scope];
175-
auto link_globs =
173+
auto link_globs =
176174
rec(visit_crate_pre = bind push_env_for_crate(cell, _),
177175
visit_crate_post = bind pop_env_for_crate(cell, _),
178-
visit_view_item_pre = bind link_glob(e, cell, cur_mod, _),
179-
visit_item_pre = bind enter_i(e, cell, cur_mod, _),
176+
visit_view_item_pre = bind link_glob(e, cell, _),
177+
visit_item_pre = bind push_env_for_item(cell, _),
180178
visit_item_post = bind pop_env_for_item(cell, _)
181179
with walk::default_visitor());
182180
walk::walk_crate(link_globs, c);
183-
184-
fn enter_i(@env e, @mutable list[scope] sc, @indexed_mod cur_mod,
185-
&@ast::item i) {
186-
push_env_for_item(sc,i);
187-
alt(i.node) {
188-
case (ast::item_mod(_, _, ?defid)) {
189-
cur_mod = e.mod_map.get(defid._1);
190-
}
191-
case (ast::item_native_mod(_, _, ?defid)) {
192-
cur_mod = e.mod_map.get(defid._1);
181+
182+
fn link_glob(@env e, @mutable list[scope] sc, &@ast::view_item vi) {
183+
fn find_mod(@env e, list[scope] sc) -> @indexed_mod {
184+
alt (sc) {
185+
case (cons[scope](scope_item(?i), ?tl)) {
186+
alt(i.node) {
187+
case (ast::item_mod(_, _, ?defid)) {
188+
ret e.mod_map.get(defid._1);
189+
}
190+
case (ast::item_native_mod(_, _, ?defid)) {
191+
ret e.mod_map.get(defid._1);
192+
}
193+
case (_) {
194+
be find_mod(e, *tl);
195+
}
196+
}
197+
}
198+
case (_) {
199+
ret e.mod_map.get(-1); //top-level
200+
}
193201
}
194-
case (_) {}
195202
}
196-
}
197-
198-
fn link_glob(@env e, @mutable list[scope] sc, @indexed_mod cur_mod,
199-
&@ast::view_item vi) {
203+
200204
alt (vi.node) {
201205
//if it really is a glob import, that is
202206
case (ast::view_item_import_glob(?path, _)) {
203-
cur_mod.glob_imports +=
204-
[follow_import(*e, *sc, path, vi.span)];
207+
find_mod(e, *sc).glob_imports
208+
+= [follow_import(*e, *sc, path, vi.span)];
205209
}
206210
case (_) {}
207211
}
@@ -518,10 +522,13 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
518522
-> option::t[def] {
519523
fn in_scope(&env e, &span sp, &ident id, &scope s, namespace ns)
520524
-> option::t[def] {
525+
//not recursing through globs
526+
let list[def] no_m = nil[def];
527+
521528
alt (s) {
522529
case (scope_crate(?c)) {
523530
auto defid = tup(ast::local_crate, -1);
524-
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
531+
ret lookup_in_local_mod(e, defid, no_m, sp, id, ns, inside);
525532
}
526533
case (scope_item(?it)) {
527534
alt (it.node) {
@@ -537,10 +544,12 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
537544
}
538545
}
539546
case (ast::item_mod(_, _, ?defid)) {
540-
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
547+
ret lookup_in_local_mod(e, defid, no_m, sp,
548+
id, ns, inside);
541549
}
542550
case (ast::item_native_mod(_, ?m, ?defid)) {
543-
ret lookup_in_local_native_mod(e, defid, sp, id, ns);
551+
ret lookup_in_local_native_mod(e, defid, no_m,
552+
sp, id, ns);
544553
}
545554
case (ast::item_ty(_, _, ?ty_params, _, _)) {
546555
if (ns == ns_type) {
@@ -768,26 +777,44 @@ fn lookup_in_mod_strict(&env e, def m, &span sp, &ident id,
768777

769778
fn lookup_in_mod(&env e, def m, &span sp, &ident id, namespace ns, dir dr)
770779
-> option::t[def] {
771-
auto defid = ast::def_id_of_def(m);
772-
if (defid._0 != ast::local_crate) { // examining a mod. in an ext. crate
773-
auto cached = e.ext_cache.find(tup(defid,id,ns));
774-
if (!option::is_none(cached)) { ret cached; }
775-
auto path = [id];
776-
if (defid._1 != -1) {
777-
path = e.ext_map.get(defid) + path;
778-
}
779-
auto fnd = lookup_external(e, defid._0, path, ns);
780-
if (!option::is_none(fnd)) {
781-
e.ext_cache.insert(tup(defid,id,ns), option::get(fnd));
782-
}
783-
ret fnd;
784-
}
780+
be lookup_in_mod_recursively(e, cons[def](m, @nil[def]), sp, id, ns, dr);
781+
}
782+
783+
// this list is simply the stack of glob imports we have passed through
784+
// (preventing cyclic glob imports from diverging)
785+
fn lookup_in_mod_recursively(&env e, list[def] m, &span sp, &ident id,
786+
namespace ns, dir dr) -> option::t[def] {
785787
alt (m) {
786-
case (ast::def_mod(?defid)) {
787-
ret lookup_in_local_mod(e, defid, sp, id, ns, dr);
788+
case (cons[def](?mod_def, ?tl)) {
789+
if (list::has(*tl, mod_def)) {
790+
ret none[def]; // import glob cycle detected; we're done
791+
}
792+
auto defid = ast::def_id_of_def(mod_def);
793+
if (defid._0 != ast::local_crate) {
794+
// examining a module in an external crate
795+
auto cached = e.ext_cache.find(tup(defid,id,ns));
796+
if (!option::is_none(cached)) { ret cached; }
797+
auto path = [id];
798+
if (defid._1 != -1) {
799+
path = e.ext_map.get(defid) + path;
800+
}
801+
auto fnd = lookup_external(e, defid._0, path, ns);
802+
if (!option::is_none(fnd)) {
803+
e.ext_cache.insert(tup(defid,id,ns), option::get(fnd));
804+
}
805+
ret fnd;
806+
}
807+
alt (mod_def) {
808+
case (ast::def_mod(?defid)) {
809+
ret lookup_in_local_mod(e, defid, m, sp, id, ns, dr);
810+
}
811+
case (ast::def_native_mod(?defid)) {
812+
ret lookup_in_local_native_mod(e, defid, m, sp, id, ns);
813+
}
814+
}
788815
}
789-
case (ast::def_native_mod(?defid)) {
790-
ret lookup_in_local_native_mod(e, defid, sp, id, ns);
816+
case (_) {
817+
e.sess.bug("lookup_in_mod_recursively needs a module"); fail;
791818
}
792819
}
793820
}
@@ -825,8 +852,14 @@ fn lookup_import(&env e, def_id defid, namespace ns) -> option::t[def] {
825852
fail;
826853
}
827854

828-
fn lookup_in_local_mod(&env e, def_id defid, &span sp, &ident id,
829-
namespace ns, dir dr) -> option::t[def] {
855+
856+
fn lookup_in_local_native_mod(&env e, def_id defid, list[def] m, &span sp,
857+
&ident id, namespace ns) -> option::t[def] {
858+
ret lookup_in_local_mod(e, defid, m, sp, id, ns, inside);
859+
}
860+
861+
fn lookup_in_local_mod(&env e, def_id defid, list[def] m, &span sp,
862+
&ident id, namespace ns, dir dr) -> option::t[def] {
830863
auto info = e.mod_map.get(defid._1);
831864
if (dr == outside && !ast::is_exported(id, option::get(info.m))) {
832865
// if we're in a native mod, then dr==inside, so info.m is some _mod
@@ -848,26 +881,24 @@ fn lookup_in_local_mod(&env e, def_id defid, &span sp, &ident id,
848881
}
849882
}
850883
// not local or explicitly imported; try globs:
851-
ret lookup_glob_in_mod(e, info, sp, id, ns, dr);
884+
ret lookup_glob_in_mod(e, info, m, sp, id, ns, dr);
852885
}
853886

854-
fn lookup_glob_in_mod(&env e, @indexed_mod info, &span sp, &ident id,
855-
namespace ns, dir dr) -> option::t[def] {
856-
fn l_i_m(&env e, &def d, &span sp, &ident id, namespace ns, dir dr)
857-
-> option::t[def] {
858-
ret lookup_in_mod(e, d, sp, id, ns, dr);
887+
fn lookup_glob_in_mod(&env e, @indexed_mod info, list[def] m, &span sp,
888+
&ident id, namespace ns, dir dr) -> option::t[def] {
889+
fn l_i_m_r(&env e, list[def] prev_ms, &def m, &span sp, &ident id,
890+
namespace ns, dir dr) -> option::t[def] {
891+
be lookup_in_mod_recursively(e, cons[def](m, @prev_ms),
892+
sp, id, ns, dr);
859893
}
860-
auto matches = vec::filter_map
861-
(bind l_i_m(e, _, sp, id, ns, dr), info.glob_imports);
894+
auto matches = vec::filter_map[def, def]
895+
(bind l_i_m_r(e, m, _, sp, id, ns, dr),
896+
info.glob_imports);
862897
if (vec::len(matches) == 0u) {
863898
ret none[def];
864899
} else if (vec::len(matches) == 1u){
865900
ret some[def](matches.(0));
866901
} else {
867-
for (def d in matches) {
868-
e.sess.span_note(sp, "'" + id + "' is defined at " +
869-
util::common::istr(ast::def_id_of_def(d)._1));
870-
}
871902
e.sess.span_err(sp, "'" + id + "' is glob-imported from" +
872903
" multiple different modules.");
873904
fail;
@@ -914,10 +945,6 @@ fn lookup_in_mie(&env e, &mod_index_entry mie, namespace ns)
914945
ret none[def];
915946
}
916947

917-
fn lookup_in_local_native_mod(&env e, def_id defid, &span sp, &ident id,
918-
namespace ns) -> option::t[def] {
919-
ret lookup_in_local_mod(e, defid, sp, id, ns, inside);
920-
}
921948

922949

923950
// Module indexing
@@ -945,9 +972,8 @@ fn index_mod(&ast::_mod md) -> mod_index {
945972
case(ast::view_item_import(?def_ident,_,_)) {
946973
add_to_index(index, def_ident, mie_view_item(it));
947974
}
948-
case(ast::view_item_import_glob(?path,_)) {
949-
//globbed imports have to be resolved lazily.
950-
}
975+
//globbed imports have to be resolved lazily.
976+
case(ast::view_item_import_glob(_,_)) {}
951977
case(ast::view_item_export(_)) {}
952978
}
953979
}
@@ -995,6 +1021,7 @@ fn index_nmod(&ast::native_mod md) -> mod_index {
9951021
case(ast::view_item_import(?def_ident,_,_)) {
9961022
add_to_index(index, def_ident, mie_view_item(it));
9971023
}
1024+
case(ast::view_item_import_glob(_,_)) {}
9981025
case(ast::view_item_export(_)) {}
9991026
}
10001027
}

src/test/compile-fail/import-glob-0.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
// error-pattern: unresolved name
2+
3+
import module_of_many_things::*;
4+
15
mod module_of_many_things {
2-
export f1, f2, f4;
6+
export f1;
7+
export f2;
8+
export f4;
9+
310
fn f1() {
411
log "f1";
512
}
@@ -14,11 +21,10 @@ mod module_of_many_things {
1421
}
1522
}
1623

17-
import module_of_many_things::*;
1824

1925
fn main() {
2026
f1();
2127
f2();
22-
f3();
28+
f999(); // 'export' currently doesn't work?
2329
f4();
2430
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
// error-pattern: unresolved name
3+
mod circ1 {
4+
import circ1::*;
5+
fn f1() {
6+
log "f1";
7+
}
8+
fn common() -> uint {
9+
ret 0u;
10+
}
11+
}
12+
13+
mod circ2 {
14+
import circ2::*;
15+
fn f2() {
16+
log "f2";
17+
}
18+
fn common() -> uint {
19+
ret 1u;
20+
}
21+
}
22+
23+
mod test {
24+
import circ1::*;
25+
26+
fn test() {
27+
f1066();
28+
}
29+
}

src/test/run-pass/import-glob-0.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ mod dug {
3131
fn also_redstone() {
3232
log "Whatever.";
3333
}
34-
fn f1() {}
3534
}
3635
}
3736
}

src/test/run-pass/import-glob-1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import a1:b1::word_traveler;
1+
import a1::b1::word_traveler;
22

33
mod a1 { //
44
mod b1 { //
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import test1::*;
2+
import test2::*;
3+
4+
mod circ1 {
5+
import circ1::*;
6+
fn f1() {
7+
log "f1";
8+
}
9+
fn common() -> uint {
10+
ret 0u;
11+
}
12+
}
13+
14+
mod circ2 {
15+
import circ2::*;
16+
fn f2() {
17+
log "f2";
18+
}
19+
fn common() -> uint {
20+
ret 1u;
21+
}
22+
}
23+
24+
mod test1 {
25+
import circ1::*;
26+
fn test1() {
27+
f1();
28+
f2();
29+
assert(common() == 0u);
30+
}
31+
}
32+
33+
mod test2 {
34+
import circ2::*;
35+
fn test2() {
36+
f1();
37+
f2();
38+
assert(common() == 1u);
39+
}
40+
}
41+
42+
43+
44+
fn main() {
45+
test1();
46+
test2();
47+
}

0 commit comments

Comments
 (0)