Skip to content

Commit f5d604f

Browse files
committed
Decode types across multiple crates. Closes #632
1 parent 33ce116 commit f5d604f

File tree

3 files changed

+71
-27
lines changed

3 files changed

+71
-27
lines changed

src/comp/metadata/csearch.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
import syntax::ast;
44
import middle::ty;
55
import std::io;
6+
import std::option;
7+
import driver::session;
8+
9+
export get_symbol;
10+
export get_type_param_count;
11+
export lookup_defs;
12+
export get_tag_variants;
13+
export get_type;
614

715
fn get_symbol(&cstore::cstore cstore, ast::def_id def) -> str {
816
auto cnum = def._0;
@@ -11,31 +19,61 @@ fn get_symbol(&cstore::cstore cstore, ast::def_id def) -> str {
1119
ret decoder::get_symbol(cdata, node_id);
1220
}
1321

14-
fn get_tag_variants(ty::ctxt tcx, ast::def_id def) -> ty::variant_info[] {
15-
auto cstore = tcx.sess.get_cstore();
22+
fn get_type_param_count(&cstore::cstore cstore, &ast::def_id def) -> uint {
1623
auto cnum = def._0;
24+
auto node_id = def._1;
1725
auto cdata = cstore::get_crate_data(cstore, cnum).data;
18-
ret decoder::get_tag_variants(cdata, def, tcx)
26+
ret decoder::get_type_param_count(cdata, node_id);
1927
}
2028

21-
fn get_type(ty::ctxt tcx, ast::def_id def) -> ty::ty_param_count_and_ty {
29+
fn lookup_defs(&cstore::cstore cstore, ast::crate_num cnum,
30+
vec[ast::ident] path) -> vec[ast::def] {
31+
auto cdata = cstore::get_crate_data(cstore, cnum).data;
32+
ret decoder::lookup_defs(cdata, cnum, path);
33+
}
34+
35+
fn get_tag_variants(ty::ctxt tcx, ast::def_id def) -> ty::variant_info[] {
2236
auto cstore = tcx.sess.get_cstore();
2337
auto cnum = def._0;
2438
auto cdata = cstore::get_crate_data(cstore, cnum).data;
25-
decoder::get_type(cdata, def, tcx)
39+
auto resolver = bind translate_def_id(tcx.sess, cnum, _);
40+
ret decoder::get_tag_variants(cdata, def, tcx, resolver)
2641
}
2742

28-
fn get_type_param_count(&cstore::cstore cstore, &ast::def_id def) -> uint {
43+
fn get_type(ty::ctxt tcx, ast::def_id def) -> ty::ty_param_count_and_ty {
44+
auto cstore = tcx.sess.get_cstore();
2945
auto cnum = def._0;
30-
auto node_id = def._1;
3146
auto cdata = cstore::get_crate_data(cstore, cnum).data;
32-
ret decoder::get_type_param_count(cdata, node_id);
47+
auto resolver = bind translate_def_id(tcx.sess, cnum, _);
48+
decoder::get_type(cdata, def, tcx, resolver)
3349
}
3450

35-
fn lookup_defs(&cstore::cstore cstore, ast::crate_num cnum,
36-
vec[ast::ident] path) -> vec[ast::def] {
37-
auto cdata = cstore::get_crate_data(cstore, cnum).data;
38-
ret decoder::lookup_defs(cdata, cnum, path);
51+
// Translates a def_id from an external crate to a def_id for the current
52+
// compilation environment. We use this when trying to load types from
53+
// external crates - if those types further refer to types in other crates
54+
// then we must translate the crate number from that encoded in the external
55+
// crate to the correct local crate number.
56+
fn translate_def_id(&session::session sess,
57+
ast::crate_num searched_crate,
58+
&ast::def_id def_id) -> ast::def_id {
59+
60+
auto ext_cnum = def_id._0;
61+
auto node_id = def_id._1;
62+
63+
assert searched_crate != ast::local_crate;
64+
assert ext_cnum != ast::local_crate;
65+
66+
auto cstore = sess.get_cstore();
67+
auto cmeta = cstore::get_crate_data(cstore, searched_crate);
68+
69+
auto local_cnum = alt (cmeta.cnum_map.find(ext_cnum)) {
70+
case (option::some(?n)) { n }
71+
case (option::none) {
72+
sess.bug("didn't find a crate in the cnum_map")
73+
}
74+
};
75+
76+
ret tup(local_cnum, node_id);
3977
}
4078

4179
// Local Variables:

src/comp/metadata/cstore.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ fn add_use_stmt_cnum(&cstore cstore, ast::node_id use_id,
8585
cstore.use_crate_map.insert(use_id, cnum);
8686
}
8787

88-
8988
// Local Variables:
9089
// mode: rust
9190
// fill-column: 78;

src/comp/metadata/decoder.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ export get_crate_attributes;
2626
export list_crate_metadata;
2727
export crate_dep;
2828
export get_crate_deps;
29+
export external_resolver;
30+
31+
// A function that takes a def_id relative to the crate being searched and
32+
// returns a def_id relative to the compilation environment, i.e. if we hit a
33+
// def_id for an item defined in another crate, somebody needs to figure out
34+
// what crate that's in and give us a def_id that makes sense for the current
35+
// build.
36+
type external_resolver = fn(&ast::def_id def_id) -> ast::def_id;
2937

3038
fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash) ->
3139
vec[ebml::doc] {
@@ -85,8 +93,10 @@ fn variant_tag_id(&ebml::doc d) -> ast::def_id {
8593
}
8694

8795
fn item_type(&ebml::doc item, ast::crate_num this_cnum,
88-
ty::ctxt tcx) -> ty::t {
89-
fn parse_external_def_id(ast::crate_num this_cnum, str s) -> ast::def_id {
96+
ty::ctxt tcx, &external_resolver extres) -> ty::t {
97+
fn parse_external_def_id(ast::crate_num this_cnum,
98+
&external_resolver extres,
99+
str s) -> ast::def_id {
90100
auto buf = str::bytes(s);
91101
auto external_def_id = parse_def_id(buf);
92102

@@ -95,17 +105,13 @@ fn item_type(&ebml::doc item, ast::crate_num this_cnum,
95105
if (external_def_id._0 == ast::local_crate) {
96106
ret tup(this_cnum, external_def_id._1);
97107
} else {
98-
// FIXME: This is completely wrong when linking against a crate
99-
// that, in turn, links against another crate. We need a mapping
100-
// from crate ID to crate "meta" attributes as part of the crate
101-
// metadata:
102-
fail "trying to load type info from a crate that is \
103-
defined in a different crate";
108+
ret extres(external_def_id);
104109
}
105110
}
106111
auto tp = ebml::get_doc(item, tag_items_data_item_type);
112+
auto def_parser = bind parse_external_def_id(this_cnum, extres, _);
107113
ret parse_ty_data(item.data, this_cnum, tp.start, tp.end - tp.start,
108-
bind parse_external_def_id(this_cnum, _), tcx);
114+
def_parser, tcx);
109115
}
110116

111117
fn item_ty_param_count(&ebml::doc item) -> uint {
@@ -180,12 +186,12 @@ fn lookup_def(ast::crate_num cnum, vec[u8] data,
180186
ret def;
181187
}
182188

183-
fn get_type(&vec[u8] data, ast::def_id def,
184-
&ty::ctxt tcx) -> ty::ty_param_count_and_ty {
189+
fn get_type(&vec[u8] data, ast::def_id def, &ty::ctxt tcx,
190+
&external_resolver extres) -> ty::ty_param_count_and_ty {
185191
auto this_cnum = def._0;
186192
auto node_id = def._1;
187193
auto item = lookup_item(node_id, data);
188-
auto t = item_type(item, this_cnum, tcx);
194+
auto t = item_type(item, this_cnum, tcx, extres);
189195
auto tp_count;
190196
auto kind_ch = item_kind(item);
191197
auto has_ty_params = kind_has_type_params(kind_ch);
@@ -204,7 +210,8 @@ fn get_symbol(&vec[u8] data, ast::node_id id) -> str {
204210
}
205211

206212
fn get_tag_variants(&vec[u8] data, ast::def_id def,
207-
&ty::ctxt tcx) -> ty::variant_info[] {
213+
&ty::ctxt tcx,
214+
&external_resolver extres) -> ty::variant_info[] {
208215
auto external_crate_id = def._0;
209216
auto data = cstore::get_crate_data(tcx.sess.get_cstore(),
210217
external_crate_id).data;
@@ -214,7 +221,7 @@ fn get_tag_variants(&vec[u8] data, ast::def_id def,
214221
auto variant_ids = tag_variant_ids(item, external_crate_id);
215222
for (ast::def_id did in variant_ids) {
216223
auto item = find_item(did._1, items);
217-
auto ctor_ty = item_type(item, external_crate_id, tcx);
224+
auto ctor_ty = item_type(item, external_crate_id, tcx, extres);
218225
let ty::t[] arg_tys = ~[];
219226
alt (ty::struct(tcx, ctor_ty)) {
220227
case (ty::ty_fn(_, ?args, _, _, _)) {

0 commit comments

Comments
 (0)