Skip to content

Commit 9bb290c

Browse files
committed
rustc: Implement non-renamed re-export across crates
First patch for issue #1115. Not yet ready for re-exported modules which are renamed when importing them.
1 parent 91249fe commit 9bb290c

File tree

7 files changed

+108
-38
lines changed

7 files changed

+108
-38
lines changed

src/comp/driver/rustc.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
162162
bind middle::ast_map::map_crate(*crate));
163163
time(time_passes, "external crate/lib resolution",
164164
bind creader::read_crates(sess, *crate));
165-
let {def_map: def_map, ext_map: ext_map} =
165+
let {def_map: def_map, ext_map: ext_map, exp_map: exp_map} =
166166
time(time_passes, "resolution",
167167
bind resolve::resolve_crate(sess, ast_map, crate));
168168
let freevars =
@@ -197,7 +197,7 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
197197
let (llmod, link_meta) =
198198
time(time_passes, "translation",
199199
bind trans::trans_crate(sess, crate, ty_cx,
200-
outputs.obj_filename, ast_map,
200+
outputs.obj_filename, exp_map, ast_map,
201201
mut_map, copy_map, last_uses));
202202
time(time_passes, "LLVM passes",
203203
bind link::write::run_passes(sess, llmod, outputs.obj_filename));
@@ -267,7 +267,7 @@ fn pretty_print_input(sess: session::session, cfg: ast::crate_cfg, input: str,
267267
ppm_typed. {
268268
crate = syntax::ext::expand::expand_crate(sess, crate);
269269
let amap = middle::ast_map::map_crate(*crate);
270-
let {def_map: def_map, ext_map: ext_map} =
270+
let {def_map: def_map, ext_map: ext_map, exp_map: _exp_map} =
271271
resolve::resolve_crate(sess, amap, crate);
272272
let freevars = freevars::annotate_freevars(def_map, crate);
273273
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, amap, freevars);

src/comp/metadata/csearch.rs

+27-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,33 @@ fn get_type_param_count(cstore: cstore::cstore, def: ast::def_id) -> uint {
2323

2424
fn lookup_defs(cstore: cstore::cstore, cnum: ast::crate_num,
2525
path: [ast::ident]) -> [ast::def] {
26-
let cdata = cstore::get_crate_data(cstore, cnum).data;
27-
ret decoder::lookup_defs(cdata, cnum, path);
26+
let result = [];
27+
for (c, data, def) in resolve_path(cstore, cnum, path) {
28+
result += [decoder::lookup_def(c, data, def)];
29+
}
30+
ret result;
31+
}
32+
33+
fn resolve_path(cstore: cstore::cstore, cnum: ast::crate_num,
34+
path: [ast::ident]) ->
35+
[(ast::crate_num, @[u8], ast::def_id)] {
36+
let cm = cstore::get_crate_data(cstore, cnum);
37+
log #fmt("resolve_path %s in crates[%d]:%s",
38+
str::connect(path, "::"), cnum, cm.name);
39+
let result = [];
40+
for def in decoder::resolve_path(path, cm.data) {
41+
if def.crate == ast::local_crate {
42+
result += [(cnum, cm.data, def)];
43+
} else {
44+
if cm.cnum_map.contains_key(def.crate) {
45+
// This reexport is itself a reexport from anther crate
46+
let next_cnum = cm.cnum_map.get(def.crate);
47+
let next_cm_data = cstore::get_crate_data(cstore, next_cnum);
48+
result += [(next_cnum, next_cm_data.data, def)];
49+
}
50+
}
51+
}
52+
ret result;
2853
}
2954

3055
fn get_tag_variants(tcx: ty::ctxt, def: ast::def_id) -> [ty::variant_info] {

src/comp/metadata/decoder.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export get_tag_variants;
1515
export get_type;
1616
export get_type_param_count;
1717
export get_type_param_kinds;
18-
export lookup_defs;
18+
export lookup_def;
19+
export resolve_path;
1920
export get_crate_attributes;
2021
export list_crate_metadata;
2122
export crate_dep;
@@ -158,14 +159,8 @@ fn resolve_path(path: [ast::ident], data: @[u8]) -> [ast::def_id] {
158159
ret result;
159160
}
160161

161-
// Crate metadata queries
162-
fn lookup_defs(data: @[u8], cnum: ast::crate_num, path: [ast::ident]) ->
163-
[ast::def] {
164-
ret vec::map(bind lookup_def(cnum, data, _), resolve_path(path, data));
165-
}
166-
167162

168-
// FIXME doesn't yet handle re-exported externals
163+
// FIXME doesn't yet handle renamed re-exported externals
169164
fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
170165
ast::def {
171166
let item = lookup_item(did_.node, data);

src/comp/metadata/encoder.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,28 @@ fn encode_module_item_paths(ebml_w: ebml::writer, module: _mod, path: [str],
141141
}
142142
}
143143

144-
fn encode_item_paths(ebml_w: ebml::writer, crate: @crate) -> [entry<str>] {
144+
fn encode_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt, crate: @crate)
145+
-> [entry<str>] {
145146
let index: [entry<str>] = [];
146147
let path: [str] = [];
147148
ebml::start_tag(ebml_w, tag_paths);
148149
encode_module_item_paths(ebml_w, crate.node.module, path, index);
150+
encode_reexport_paths(ebml_w, ecx, index);
149151
ebml::end_tag(ebml_w);
150152
ret index;
151153
}
152154

155+
fn encode_reexport_paths(ebml_w: ebml::writer,
156+
ecx: @encode_ctxt, &index: [entry<str>]) {
157+
ecx.ccx.exp_map.items {|path, def|
158+
index += [{val: path, pos: ebml_w.writer.tell()}];
159+
ebml::start_tag(ebml_w, tag_paths_data_item);
160+
encode_name(ebml_w, path);
161+
encode_def_id(ebml_w, ast_util::def_id_of_def(def));
162+
ebml::end_tag(ebml_w);
163+
}
164+
}
165+
153166

154167
// Item info table encoding
155168
fn encode_family(ebml_w: ebml::writer, c: u8) {
@@ -602,7 +615,7 @@ fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> str {
602615
// Encode and index the paths.
603616

604617
ebml::start_tag(ebml_w, tag_paths);
605-
let paths_index = encode_item_paths(ebml_w, crate);
618+
let paths_index = encode_item_paths(ebml_w, ecx, crate);
606619
let paths_buckets = create_index(paths_index, hash_path);
607620
encode_index(ebml_w, paths_buckets, write_str);
608621
ebml::end_tag(ebml_w);

src/comp/middle/resolve.rs

+54-20
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ import core::{vec, option, str};
1515
import std::list;
1616
import std::map::hashmap;
1717
import std::list::{list, nil, cons};
18-
import option::{some, none, is_none};
18+
import option::{some, none, is_none, is_some};
1919
import syntax::print::pprust::*;
2020

2121
export resolve_crate;
2222
export def_map;
2323
export ext_map;
24+
export exp_map;
2425

2526
// Resolving happens in two passes. The first pass collects defids of all
2627
// (internal) imports and modules, so that they can be looked up when needed,
@@ -97,15 +98,17 @@ type indexed_mod = {
9798

9899
type def_map = hashmap<node_id, def>;
99100
type ext_map = hashmap<def_id, [ident]>;
101+
type exp_map = hashmap<str, def>;
100102

101103
type env =
102104
{cstore: cstore::cstore,
103105
def_map: def_map,
104106
ast_map: ast_map::map,
105107
imports: hashmap<ast::node_id, import_state>,
108+
exp_map: exp_map,
106109
mod_map: hashmap<ast::node_id, @indexed_mod>,
107110
block_map: hashmap<ast::node_id, [glob_imp_def]>,
108-
ext_map: hashmap<def_id, [ident]>,
111+
ext_map: ext_map,
109112
ext_cache: ext_hash,
110113
used_imports: {mutable track: bool,
111114
mutable data: [ast::node_id]},
@@ -121,12 +124,13 @@ tag dir { inside; outside; }
121124
tag namespace { ns_value; ns_type; ns_module; }
122125

123126
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} {
125128
let e =
126129
@{cstore: sess.get_cstore(),
127130
def_map: new_int_hash(),
128131
ast_map: amap,
129132
imports: new_int_hash(),
133+
exp_map: new_str_hash(),
130134
mod_map: new_int_hash(),
131135
block_map: new_int_hash(),
132136
ext_map: new_def_hash(),
@@ -138,12 +142,12 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
138142
map_crate(e, crate);
139143
resolve_imports(*e);
140144
check_for_collisions(e, *crate);
141-
check_bad_exports(e);
145+
check_exports(e);
142146
resolve_names(e, crate);
143147
if sess.get_opts().warn_unused_imports {
144148
check_unused_imports(e);
145149
}
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};
147151
}
148152

149153
// 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,
15271531
for elt: T in elts { add_name(ch, sp, id(elt)); }
15281532
}
15291533

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+
}
15391578
}
15401579

15411580
e.mod_map.values {|val|
@@ -1545,12 +1584,7 @@ fn check_bad_exports(e: @env) {
15451584
alt vi.node {
15461585
ast::view_item_export(idents, _) {
15471586
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);
15541588
}
15551589
}
15561590
_ { }

src/comp/middle/trans.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import std::map::{new_int_hash, new_str_hash};
2020
import option::{some, none};
2121
import driver::session;
2222
import front::attr;
23-
import middle::{ty, gc};
23+
import middle::{ty, gc, resolve};
2424
import middle::freevars::*;
2525
import back::{link, abi, upcall};
2626
import syntax::{ast, ast_util};
@@ -5511,8 +5511,9 @@ fn write_abi_version(ccx: @crate_ctxt) {
55115511
}
55125512

55135513
fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
5514-
output: str, amap: ast_map::map, mut_map: mut::mut_map,
5515-
copy_map: alias::copy_map, last_uses: last_use::last_uses)
5514+
output: str, emap: resolve::exp_map, amap: ast_map::map,
5515+
mut_map: mut::mut_map, copy_map: alias::copy_map,
5516+
last_uses: last_use::last_uses)
55165517
-> (ModuleRef, link::link_meta) {
55175518
let sha = std::sha1::mk_sha1();
55185519
let link_meta = link::build_link_meta(sess, *crate, output, sha);
@@ -5567,6 +5568,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
55675568
intrinsics: intrinsics,
55685569
item_ids: new_int_hash::<ValueRef>(),
55695570
ast_map: amap,
5571+
exp_map: emap,
55705572
item_symbols: new_int_hash::<str>(),
55715573
mutable main_fn: none::<ValueRef>,
55725574
link_meta: link_meta,

src/comp/middle/trans_common.rs

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ type crate_ctxt =
8484
intrinsics: hashmap<str, ValueRef>,
8585
item_ids: hashmap<ast::node_id, ValueRef>,
8686
ast_map: ast_map::map,
87+
exp_map: hashmap<str, ast::def>,
8788
item_symbols: hashmap<ast::node_id, str>,
8889
mutable main_fn: option::t<ValueRef>,
8990
link_meta: link::link_meta,

0 commit comments

Comments
 (0)