@@ -15,12 +15,13 @@ import core::{vec, option, str};
15
15
import std:: list;
16
16
import std:: map:: hashmap;
17
17
import std:: list:: { list, nil, cons} ;
18
- import option:: { some, none, is_none} ;
18
+ import option:: { some, none, is_none, is_some } ;
19
19
import syntax:: print:: pprust:: * ;
20
20
21
21
export resolve_crate;
22
22
export def_map;
23
23
export ext_map;
24
+ export exp_map;
24
25
25
26
// Resolving happens in two passes. The first pass collects defids of all
26
27
// (internal) imports and modules, so that they can be looked up when needed,
@@ -97,15 +98,17 @@ type indexed_mod = {
97
98
98
99
type def_map = hashmap < node_id , def > ;
99
100
type ext_map = hashmap < def_id , [ ident ] > ;
101
+ type exp_map = hashmap < str , def > ;
100
102
101
103
type env =
102
104
{ cstore : cstore:: cstore ,
103
105
def_map : def_map ,
104
106
ast_map : ast_map:: map ,
105
107
imports : hashmap < ast:: node_id , import_state > ,
108
+ exp_map : exp_map ,
106
109
mod_map : hashmap < ast:: node_id , @indexed_mod > ,
107
110
block_map : hashmap < ast:: node_id , [ glob_imp_def ] > ,
108
- ext_map : hashmap < def_id , [ ident ] > ,
111
+ ext_map : ext_map ,
109
112
ext_cache : ext_hash ,
110
113
used_imports : { mutable track: bool ,
111
114
mutable data: [ ast:: node_id ] } ,
@@ -121,12 +124,13 @@ tag dir { inside; outside; }
121
124
tag namespace { ns_value; ns_type; ns_module; }
122
125
123
126
fn resolve_crate ( sess : session , amap : ast_map:: map , crate : @ast:: crate ) ->
124
- { def_map : def_map , ext_map : ext_map } {
127
+ { def_map : def_map , ext_map : ext_map , exp_map : exp_map } {
125
128
let e =
126
129
@{ cstore: sess. get_cstore ( ) ,
127
130
def_map: new_int_hash ( ) ,
128
131
ast_map: amap,
129
132
imports: new_int_hash ( ) ,
133
+ exp_map: new_str_hash ( ) ,
130
134
mod_map: new_int_hash ( ) ,
131
135
block_map: new_int_hash ( ) ,
132
136
ext_map: new_def_hash ( ) ,
@@ -138,12 +142,12 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
138
142
map_crate ( e, crate ) ;
139
143
resolve_imports ( * e) ;
140
144
check_for_collisions ( e, * crate ) ;
141
- check_bad_exports ( e) ;
145
+ check_exports ( e) ;
142
146
resolve_names ( e, crate ) ;
143
147
if sess. get_opts ( ) . warn_unused_imports {
144
148
check_unused_imports ( e) ;
145
149
}
146
- ret { def_map : e. def_map , ext_map : e. ext_map } ;
150
+ ret { def_map : e. def_map , ext_map : e. ext_map , exp_map : e . exp_map } ;
147
151
}
148
152
149
153
// Locate all modules and imports and index them, so that the next passes can
@@ -1527,15 +1531,50 @@ fn ensure_unique<T>(e: env, sp: span, elts: [T], id: fn(T) -> ident,
1527
1531
for elt: T in elts { add_name ( ch, sp, id ( elt) ) ; }
1528
1532
}
1529
1533
1530
- fn check_bad_exports ( e : @env ) {
1531
- fn lookup_glob_any ( e : env , info : @indexed_mod , sp : span , ident : ident ) ->
1532
- bool {
1533
- ret !option:: is_none ( lookup_glob_in_mod ( e, info, sp, ident, ns_module,
1534
- inside) ) ||
1535
- !option:: is_none ( lookup_glob_in_mod ( e, info, sp, ident,
1536
- ns_value, inside) ) ||
1537
- !option:: is_none ( lookup_glob_in_mod ( e, info, sp, ident,
1538
- ns_type, inside) ) ;
1534
+ fn check_exports ( e : @env ) {
1535
+ fn lookup_glob_any ( e : @env , info : @indexed_mod , sp : span , path : str ,
1536
+ ident : ident ) -> bool {
1537
+ let lookup =
1538
+ bind lookup_glob_in_mod ( * e, info, sp, ident, _, inside) ;
1539
+ let ( m, v, t) = ( lookup ( ns_module) ,
1540
+ lookup ( ns_value) ,
1541
+ lookup ( ns_type) ) ;
1542
+ maybe_add_reexport ( e, path + ident, m) ;
1543
+ maybe_add_reexport ( e, path + ident, v) ;
1544
+ maybe_add_reexport ( e, path + ident, t) ;
1545
+ ret is_some( m) || is_some ( v) || is_some ( t) ;
1546
+ }
1547
+
1548
+ fn maybe_add_reexport ( e : @env , path : str , def : option:: t < def > ) {
1549
+ if option:: is_some ( def) {
1550
+ e. exp_map . insert ( path, option:: get ( def) ) ;
1551
+ }
1552
+ }
1553
+
1554
+ fn check_export ( e : @env , ident : str , val : @indexed_mod , vi : @view_item ) {
1555
+ if val. index . contains_key ( ident) {
1556
+ let xs = val. index . get ( ident) ;
1557
+ list:: iter ( xs) { |x|
1558
+ alt x {
1559
+ mie_import_ident( id, _) {
1560
+ alt e. imports . get ( id) {
1561
+ resolved ( v, t, m, rid, _) {
1562
+ maybe_add_reexport ( e, val. path + rid, v) ;
1563
+ maybe_add_reexport ( e, val. path + rid, t) ;
1564
+ maybe_add_reexport ( e, val. path + rid, m) ;
1565
+ }
1566
+ _ { }
1567
+ }
1568
+ }
1569
+ _ { }
1570
+ }
1571
+ }
1572
+ } else if lookup_glob_any ( e, val, vi. span , val. path , ident) {
1573
+ // do nothing
1574
+ } else {
1575
+ e. sess . span_warn ( vi. span ,
1576
+ #fmt ( "exported item %s is not defined" , ident) ) ;
1577
+ }
1539
1578
}
1540
1579
1541
1580
e. mod_map . values { |val|
@@ -1545,12 +1584,7 @@ fn check_bad_exports(e: @env) {
1545
1584
alt vi. node {
1546
1585
ast:: view_item_export ( idents, _) {
1547
1586
for ident in idents {
1548
- if !val. index . contains_key ( ident) &&
1549
- !lookup_glob_any ( * e, val, vi. span , ident) {
1550
- e. sess . span_warn ( vi. span ,
1551
- "exported item " + ident +
1552
- " is not defined" ) ;
1553
- }
1587
+ check_export ( e, ident, val, vi) ;
1554
1588
}
1555
1589
}
1556
1590
_ { }
0 commit comments