@@ -43,7 +43,7 @@ tag scope {
43
43
}
44
44
45
45
tag import_state {
46
- todo( @ast : : view_item, list[ scope] ) ;
46
+ todo( @ast : : view_item, list[ scope] ) ; // only used for explicit imports
47
47
resolving ( span) ;
48
48
resolved ( option:: t[ def] /* value */ ,
49
49
option:: t[ def] /* type */ ,
@@ -77,7 +77,8 @@ tag mod_index_entry {
77
77
type mod_index = hashmap [ ident, list[ mod_index_entry] ] ;
78
78
79
79
type indexed_mod = rec ( option:: t[ ast:: _mod ] m ,
80
- mod_index index, vec[ def] glob_imports ) ;
80
+ mod_index index, vec[ def] glob_imports ,
81
+ hashmap[ str, import_state] glob_imported_names ) ;
81
82
/* native modules can't contain tags, and we don't store their ASTs because we
82
83
only need to look at them to determine exports, which they can't control.*/
83
84
// It should be safe to use index to memoize lookups of globbed names.
@@ -141,7 +142,9 @@ fn map_crate(&@env e, &ast::crate c) {
141
142
// Register the top-level mod
142
143
e. mod_map . insert ( -1 , @rec ( m=some ( c. node . module ) ,
143
144
index=index_mod ( c. node . module ) ,
144
- glob_imports=vec:: empty[ def] ( ) ) ) ;
145
+ glob_imports=vec:: empty[ def] ( ) ,
146
+ glob_imported_names
147
+ =new_str_hash[ import_state] ( ) ) ) ;
145
148
walk:: walk_crate ( index_names, c) ;
146
149
147
150
fn index_vi ( @env e , @mutable list[ scope] sc , & @ast:: view_item i) {
@@ -158,14 +161,18 @@ fn map_crate(&@env e, &ast::crate c) {
158
161
case ( ast:: item_mod ( _, ?md, ?defid) ) {
159
162
e. mod_map . insert ( defid. _1 ,
160
163
@rec ( m=some ( md) , index=index_mod ( md) ,
161
- glob_imports=vec:: empty[ def] ( ) ) ) ;
164
+ glob_imports=vec:: empty[ def] ( ) ,
165
+ glob_imported_names
166
+ =new_str_hash[ import_state] ( ) ) ) ;
162
167
e. ast_map . insert ( defid, i) ;
163
168
}
164
169
case ( ast:: item_native_mod ( _, ?nmd, ?defid) ) {
165
170
e. mod_map . insert ( defid. _1 ,
166
171
@rec ( m=none[ ast:: _mod] ,
167
172
index=index_nmod ( nmd) ,
168
- glob_imports=vec:: empty[ def] ( ) ) ) ;
173
+ glob_imports=vec:: empty[ def] ( ) ,
174
+ glob_imported_names
175
+ =new_str_hash[ import_state] ( ) ) ) ;
169
176
e. ast_map . insert ( defid, i) ;
170
177
}
171
178
case ( ast:: item_const ( _, _, _, ?defid, _) ) {
@@ -542,12 +549,11 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
542
549
fn in_scope ( & env e, & span sp, & ident id, & scope s, namespace ns)
543
550
-> option:: t [ def ] {
544
551
//not recursing through globs
545
- let list[ def] no_m = nil[ def] ;
546
552
547
553
alt ( s) {
548
554
case ( scope_crate ( ?c) ) {
549
555
auto defid = tup ( ast:: local_crate, -1 ) ;
550
- ret lookup_in_local_mod ( e, defid, no_m , sp, id, ns, inside) ;
556
+ ret lookup_in_local_mod ( e, defid, sp, id, ns, inside) ;
551
557
}
552
558
case ( scope_item ( ?it) ) {
553
559
alt ( it. node ) {
@@ -563,12 +569,10 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
563
569
}
564
570
}
565
571
case ( ast:: item_mod ( _, _, ?defid) ) {
566
- ret lookup_in_local_mod ( e, defid, no_m, sp,
567
- id, ns, inside) ;
572
+ ret lookup_in_local_mod ( e, defid, sp, id, ns, inside) ;
568
573
}
569
574
case ( ast:: item_native_mod ( _, ?m, ?defid) ) {
570
- ret lookup_in_local_native_mod ( e, defid, no_m,
571
- sp, id, ns) ;
575
+ ret lookup_in_local_native_mod ( e, defid, sp, id, ns) ;
572
576
}
573
577
case ( ast:: item_ty ( _, _, ?ty_params, _, _) ) {
574
578
if ( ns == ns_type) {
@@ -796,44 +800,27 @@ fn lookup_in_mod_strict(&env e, def m, &span sp, &ident id,
796
800
797
801
fn lookup_in_mod ( & env e, def m, & span sp, & ident id, namespace ns, dir dr)
798
802
-> option:: t [ def ] {
799
- be lookup_in_mod_recursively ( e, cons[ def] ( m, @nil[ def] ) , sp, id, ns, dr) ;
800
- }
801
-
802
- // this list is simply the stack of glob imports we have passed through
803
- // (preventing cyclic glob imports from diverging)
804
- fn lookup_in_mod_recursively ( & env e, list[ def] m , & span sp, & ident id,
805
- namespace ns, dir dr) -> option:: t [ def ] {
803
+ auto defid = ast:: def_id_of_def ( m) ;
804
+ if ( defid. _0 != ast:: local_crate) {
805
+ // examining a module in an external crate
806
+ auto cached = e. ext_cache . find ( tup ( defid, id, ns) ) ;
807
+ if ( !option:: is_none ( cached) ) { ret cached; }
808
+ auto path = [ id] ;
809
+ if ( defid. _1 != -1 ) {
810
+ path = e. ext_map . get ( defid) + path;
811
+ }
812
+ auto fnd = lookup_external ( e, defid. _0 , path, ns) ;
813
+ if ( !option:: is_none ( fnd) ) {
814
+ e. ext_cache . insert ( tup ( defid, id, ns) , option:: get ( fnd) ) ;
815
+ }
816
+ ret fnd;
817
+ }
806
818
alt ( m) {
807
- case ( cons[ def] ( ?mod_def, ?tl) ) {
808
- if ( list:: has ( * tl, mod_def) ) {
809
- ret none[ def] ; // import glob cycle detected; we're done
810
- }
811
- auto defid = ast:: def_id_of_def ( mod_def) ;
812
- if ( defid. _0 != ast:: local_crate) {
813
- // examining a module in an external crate
814
- auto cached = e. ext_cache . find ( tup ( defid, id, ns) ) ;
815
- if ( !option:: is_none ( cached) ) { ret cached; }
816
- auto path = [ id] ;
817
- if ( defid. _1 != -1 ) {
818
- path = e. ext_map . get ( defid) + path;
819
- }
820
- auto fnd = lookup_external ( e, defid. _0 , path, ns) ;
821
- if ( !option:: is_none ( fnd) ) {
822
- e. ext_cache . insert ( tup ( defid, id, ns) , option:: get ( fnd) ) ;
823
- }
824
- ret fnd;
825
- }
826
- alt ( mod_def) {
827
- case ( ast:: def_mod ( ?defid) ) {
828
- ret lookup_in_local_mod ( e, defid, m, sp, id, ns, dr) ;
829
- }
830
- case ( ast:: def_native_mod ( ?defid) ) {
831
- ret lookup_in_local_native_mod ( e, defid, m, sp, id, ns) ;
832
- }
833
- }
819
+ case ( ast:: def_mod ( ?defid) ) {
820
+ ret lookup_in_local_mod ( e, defid, sp, id, ns, dr) ;
834
821
}
835
- case ( _ ) {
836
- e . sess . bug ( "lookup_in_mod_recursively needs a module" ) ; fail ;
822
+ case ( ast :: def_native_mod ( ?defid ) ) {
823
+ ret lookup_in_local_native_mod ( e , defid , sp , id , ns ) ;
837
824
}
838
825
}
839
826
}
@@ -872,18 +859,18 @@ fn lookup_import(&env e, def_id defid, namespace ns) -> option::t[def] {
872
859
}
873
860
874
861
875
- fn lookup_in_local_native_mod ( & env e, def_id defid, list [ def ] m , & span sp,
862
+ fn lookup_in_local_native_mod ( & env e, def_id defid, & span sp,
876
863
& ident id, namespace ns) -> option:: t [ def ] {
877
- ret lookup_in_local_mod ( e, defid, m , sp, id, ns, inside) ;
864
+ ret lookup_in_local_mod ( e, defid, sp, id, ns, inside) ;
878
865
}
879
866
880
- fn lookup_in_local_mod ( & env e, def_id defid, list [ def ] m , & span sp,
867
+ fn lookup_in_local_mod ( & env e, def_id defid, & span sp,
881
868
& ident id, namespace ns, dir dr) -> option:: t [ def ] {
882
869
auto info = e. mod_map . get ( defid. _1 ) ;
883
- if ( dr == outside && !ast:: is_exported ( id, option:: get ( info. m ) ) ) {
884
- // if we're in a native mod, then dr==inside, so info.m is some _mod
885
- ret none[ def] ; // name is not visible
886
- }
870
+ if ( dr == outside && !ast:: is_exported ( id, option:: get ( info. m ) ) ) {
871
+ // if we're in a native mod, then dr==inside, so info.m is some _mod
872
+ ret none[ def] ; // name is not visible
873
+ }
887
874
alt ( info. index . find ( id) ) {
888
875
case ( none[ list[ mod_index_entry] ] ) { }
889
876
case ( some[ list[ mod_index_entry] ] ( ?lst) ) {
@@ -900,31 +887,56 @@ fn lookup_in_local_mod(&env e, def_id defid, list[def] m, &span sp,
900
887
}
901
888
}
902
889
// not local or explicitly imported; try globs:
903
- ret lookup_glob_in_mod ( e, info, m , sp, id, ns, dr) ;
890
+ ret lookup_glob_in_mod ( e, info, sp, id, ns, dr) ;
904
891
}
905
892
906
- fn lookup_glob_in_mod ( & env e, @indexed_mod info , list[ def] m , & span sp,
907
- & ident id, namespace ns, dir dr) -> option:: t [ def ] {
908
- fn l_i_m_r ( & env e, list[ def] prev_ms , & def m, & span sp, & ident id,
909
- namespace ns, dir dr) -> option:: t [ def ] {
910
- be lookup_in_mod_recursively ( e, cons[ def] ( m, @prev_ms) ,
911
- sp, id, ns, dr) ;
893
+ fn lookup_glob_in_mod ( & env e, @indexed_mod info , & span sp,
894
+ & ident id, namespace wanted_ns, dir dr)
895
+ -> option:: t [ def ] {
896
+ fn per_ns ( & env e, @indexed_mod info , & span sp, & ident id,
897
+ namespace ns, dir dr) -> option:: t [ def ] {
898
+ fn l_i_m_r ( & env e, & def m, & span sp, & ident id,
899
+ namespace ns, dir dr) -> option:: t [ def ] {
900
+ be lookup_in_mod ( e, m, sp, id, ns, dr) ;
901
+ }
902
+
903
+ auto matches = vec:: filter_map[ def, def]
904
+ ( bind l_i_m_r ( e, _, sp, id, ns, dr) ,
905
+ info. glob_imports ) ;
906
+ if ( vec:: len ( matches) == 0 u) {
907
+ ret none[ def] ;
908
+ } else if ( vec:: len ( matches) == 1 u) {
909
+ ret some[ def] ( matches. ( 0 ) ) ;
910
+ } else {
911
+ for ( def match in matches) {
912
+ e. sess . span_note ( e. ast_map . get
913
+ ( ast:: def_id_of_def ( match ) ) . span ,
914
+ "'" + id + "' is defined here." ) ;
915
+ }
916
+ e. sess . span_err ( sp, "'" + id + "' is glob-imported from" +
917
+ " multiple different modules." ) ;
918
+ fail;
919
+ }
912
920
}
913
- auto matches = vec:: filter_map[ def, def]
914
- ( bind l_i_m_r ( e, m, _, sp, id, ns, dr) ,
915
- info. glob_imports ) ;
916
- if ( vec:: len ( matches) == 0 u) {
917
- ret none[ def] ;
918
- } else if ( vec:: len ( matches) == 1 u) {
919
- ret some[ def] ( matches. ( 0 ) ) ;
920
- } else {
921
- for ( def match in matches) {
922
- e. sess . span_note ( e. ast_map . get ( ast:: def_id_of_def ( match ) ) . span ,
923
- "'" + id + "' is defined here." ) ;
921
+ // since we don't know what names we have in advance,
922
+ // absence takes the place of todo()
923
+ if ( !info. glob_imported_names . contains_key ( id) ) {
924
+ info. glob_imported_names . insert ( id, resolving ( sp) ) ;
925
+ auto val = per_ns ( e, info, sp, id, ns_value, dr) ;
926
+ auto typ = per_ns ( e, info, sp, id, ns_type, dr) ;
927
+ auto md = per_ns ( e, info, sp, id, ns_module, dr) ;
928
+ info. glob_imported_names . insert ( id, resolved ( val, typ, md) ) ;
929
+ }
930
+ alt ( info. glob_imported_names . get ( id) ) {
931
+ case ( todo ( _, _) ) { e. sess . bug ( "Shouldn't've put a todo in." ) ; }
932
+ case ( resolving ( ?sp) ) {
933
+ ret none[ def] ; //circularity is okay in import globs
934
+ }
935
+ case ( resolved ( ?val, ?typ, ?md) ) {
936
+ ret alt ( wanted_ns) { case ( ns_value) { val }
937
+ case ( ns_type) { typ }
938
+ case ( ns_module) { md } } ;
924
939
}
925
- e. sess . span_err ( sp, "'" + id + "' is glob-imported from" +
926
- " multiple different modules." ) ;
927
- fail;
928
940
}
929
941
}
930
942
0 commit comments