Make cross-crate calls to class methods work
This commit is contained in:
@@ -78,7 +78,7 @@ const tag_path: uint = 0x40u;
|
|||||||
const tag_path_len: uint = 0x41u;
|
const tag_path_len: uint = 0x41u;
|
||||||
const tag_path_elt_mod: uint = 0x42u;
|
const tag_path_elt_mod: uint = 0x42u;
|
||||||
const tag_path_elt_name: uint = 0x43u;
|
const tag_path_elt_name: uint = 0x43u;
|
||||||
const tag_items_class_member: uint = 0x44u;
|
const tag_item_field: uint = 0x44u;
|
||||||
|
|
||||||
// used to encode crate_ctxt side tables
|
// used to encode crate_ctxt side tables
|
||||||
enum astencode_tag { // Reserves 0x50 -- 0x6f
|
enum astencode_tag { // Reserves 0x50 -- 0x6f
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import std::map::hashmap;
|
|||||||
|
|
||||||
export get_symbol;
|
export get_symbol;
|
||||||
export get_class_fields;
|
export get_class_fields;
|
||||||
|
export get_class_method;
|
||||||
// export get_class_method_ids;
|
// export get_class_method_ids;
|
||||||
export get_field_type;
|
export get_field_type;
|
||||||
export get_type_param_count;
|
export get_type_param_count;
|
||||||
@@ -179,6 +180,16 @@ fn get_impl_method(cstore: cstore::cstore, def: ast::def_id, mname: str)
|
|||||||
decoder::get_impl_method(cdata, def.node, mname)
|
decoder::get_impl_method(cdata, def.node, mname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Because classes use the iface format rather than the impl format
|
||||||
|
for their methods (so that get_iface_methods can be reused to get
|
||||||
|
class methods), classes require a slightly different version of
|
||||||
|
get_impl_method. Sigh. */
|
||||||
|
fn get_class_method(cstore: cstore::cstore, def: ast::def_id, mname: str)
|
||||||
|
-> ast::def_id {
|
||||||
|
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||||
|
decoder::get_class_method(cdata, def.node, mname)
|
||||||
|
}
|
||||||
|
|
||||||
fn item_is_intrinsic(cstore: cstore::cstore, def: ast::def_id) -> bool {
|
fn item_is_intrinsic(cstore: cstore::cstore, def: ast::def_id) -> bool {
|
||||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||||
decoder::item_is_intrinsic(cdata, def.node)
|
decoder::item_is_intrinsic(cdata, def.node)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export get_enum_variants;
|
|||||||
export get_type;
|
export get_type;
|
||||||
export get_type_param_count;
|
export get_type_param_count;
|
||||||
export get_impl_iface;
|
export get_impl_iface;
|
||||||
|
export get_class_method;
|
||||||
export get_impl_method;
|
export get_impl_method;
|
||||||
export lookup_def;
|
export lookup_def;
|
||||||
export lookup_item_name;
|
export lookup_item_name;
|
||||||
@@ -289,6 +290,25 @@ fn get_impl_method(cdata: cmd, id: ast::node_id, name: str) -> ast::def_id {
|
|||||||
option::get(found)
|
option::get(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_class_method(cdata: cmd, id: ast::node_id, name: str) -> ast::def_id {
|
||||||
|
let items = ebml::get_doc(ebml::doc(cdata.data), tag_items);
|
||||||
|
let mut found = none;
|
||||||
|
let cls_items = alt maybe_find_item(id, items) {
|
||||||
|
some(it) { it }
|
||||||
|
none { fail (#fmt("get_class_method: class id not found \
|
||||||
|
when looking up method %s", name)) }};
|
||||||
|
ebml::tagged_docs(cls_items, tag_item_method) {|mid|
|
||||||
|
let m_did = class_member_id(mid, cdata);
|
||||||
|
if item_name(mid) == name {
|
||||||
|
found = some(m_did);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alt found {
|
||||||
|
some(found) { found }
|
||||||
|
none { fail (#fmt("get_class_method: no method named %s", name)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn item_is_intrinsic(cdata: cmd, id: ast::node_id) -> bool {
|
fn item_is_intrinsic(cdata: cmd, id: ast::node_id) -> bool {
|
||||||
let mut intrinsic = false;
|
let mut intrinsic = false;
|
||||||
ebml::tagged_docs(lookup_item(id, cdata.data), tag_item_is_intrinsic,
|
ebml::tagged_docs(lookup_item(id, cdata.data), tag_item_is_intrinsic,
|
||||||
@@ -306,6 +326,7 @@ fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path {
|
|||||||
|
|
||||||
fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt, maps: maps,
|
fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt, maps: maps,
|
||||||
id: ast::node_id) -> csearch::found_ast {
|
id: ast::node_id) -> csearch::found_ast {
|
||||||
|
#debug("Looking up item: %d", id);
|
||||||
let item_doc = lookup_item(id, cdata.data);
|
let item_doc = lookup_item(id, cdata.data);
|
||||||
let path = vec::init(item_path(item_doc));
|
let path = vec::init(item_path(item_doc));
|
||||||
alt astencode::decode_inlined_item(cdata, tcx, maps, path, item_doc) {
|
alt astencode::decode_inlined_item(cdata, tcx, maps, path, item_doc) {
|
||||||
@@ -389,6 +410,7 @@ fn get_impls_for_mod(cdata: cmd, m_id: ast::node_id,
|
|||||||
@result
|
@result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Works for both classes and ifaces */
|
||||||
fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
||||||
-> @[ty::method] {
|
-> @[ty::method] {
|
||||||
let data = cdata.data;
|
let data = cdata.data;
|
||||||
@@ -417,7 +439,7 @@ fn get_class_members(cdata: cmd, id: ast::node_id,
|
|||||||
let data = cdata.data;
|
let data = cdata.data;
|
||||||
let item = lookup_item(id, data);
|
let item = lookup_item(id, data);
|
||||||
let mut result = [];
|
let mut result = [];
|
||||||
ebml::tagged_docs(item, tag_items_data_item) {|an_item|
|
ebml::tagged_docs(item, tag_item_field) {|an_item|
|
||||||
if item_family(an_item) == family {
|
if item_family(an_item) == family {
|
||||||
let name = item_name(an_item);
|
let name = item_name(an_item);
|
||||||
let did = class_member_id(an_item, cdata);
|
let did = class_member_id(an_item, cdata);
|
||||||
|
|||||||
@@ -353,19 +353,12 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
|
|||||||
|
|
||||||
/* Returns an index of items in this class */
|
/* Returns an index of items in this class */
|
||||||
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||||
id: node_id, path: ast_map::path, name: ident,
|
id: node_id, path: ast_map::path,
|
||||||
tps: [ty_param], items: [@class_item])
|
items: [@class_item],
|
||||||
|
global_index: @mutable[entry<int>])
|
||||||
-> [entry<int>] {
|
-> [entry<int>] {
|
||||||
let index = @mutable [];
|
let index = @mutable [];
|
||||||
|
|
||||||
let tcx = ecx.ccx.tcx;
|
let tcx = ecx.ccx.tcx;
|
||||||
encode_def_id(ebml_w, local_def(id));
|
|
||||||
encode_family(ebml_w, 'C');
|
|
||||||
encode_type_param_bounds(ebml_w, ecx, tps);
|
|
||||||
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
|
|
||||||
encode_name(ebml_w, name);
|
|
||||||
encode_path(ebml_w, path, ast_map::path_name(name));
|
|
||||||
|
|
||||||
for ci in items {
|
for ci in items {
|
||||||
/* We encode both private and public fields -- need to include
|
/* We encode both private and public fields -- need to include
|
||||||
private fields to get the offsets right */
|
private fields to get the offsets right */
|
||||||
@@ -380,22 +373,23 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
|||||||
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
|
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
|
||||||
/* TODO: mutability */
|
/* TODO: mutability */
|
||||||
encode_def_id(ebml_w, local_def(id));
|
encode_def_id(ebml_w, local_def(id));
|
||||||
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
class_method(m) {
|
class_method(m) {
|
||||||
*index += [{val: m.id, pos: ebml_w.writer.tell()}];
|
*index += [{val: m.id, pos: ebml_w.writer.tell()}];
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
/* Not sure whether we really need to have two indices,
|
||||||
encode_family(ebml_w, 'h');
|
but it works for now -- tjc */
|
||||||
encode_name(ebml_w, m.ident);
|
*global_index += [{val: m.id, pos: ebml_w.writer.tell()}];
|
||||||
let impl_path = path + [ast_map::path_name(m.ident)];
|
let impl_path = path + [ast_map::path_name(m.ident)];
|
||||||
/*
|
/*
|
||||||
Recall methods are (currently) monomorphic, and we don't
|
Recall methods are (currently) monomorphic, and we don't
|
||||||
repeat the class's ty params in the method decl
|
repeat the class's ty params in the method decl
|
||||||
*/
|
*/
|
||||||
|
#debug("encode_info_for_class: doing %s %d", m.ident, m.id);
|
||||||
encode_info_for_method(ecx, ebml_w, impl_path,
|
encode_info_for_method(ecx, ebml_w, impl_path,
|
||||||
should_inline(m.attrs), id, m, []);
|
should_inline(m.attrs), id, m, []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ebml_w.end_tag();
|
|
||||||
}
|
}
|
||||||
*index
|
*index
|
||||||
}
|
}
|
||||||
@@ -404,6 +398,7 @@ fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
|||||||
id: node_id, ident: ident, path: ast_map::path,
|
id: node_id, ident: ident, path: ast_map::path,
|
||||||
item: option<@item>, tps: [ty_param], decl: fn_decl) {
|
item: option<@item>, tps: [ty_param], decl: fn_decl) {
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
|
encode_name(ebml_w, ident);
|
||||||
encode_def_id(ebml_w, local_def(id));
|
encode_def_id(ebml_w, local_def(id));
|
||||||
encode_family(ebml_w, purity_fn_family(decl.purity));
|
encode_family(ebml_w, purity_fn_family(decl.purity));
|
||||||
encode_type_param_bounds(ebml_w, ecx, tps);
|
encode_type_param_bounds(ebml_w, ecx, tps);
|
||||||
@@ -469,10 +464,16 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
let tcx = ecx.ccx.tcx;
|
let tcx = ecx.ccx.tcx;
|
||||||
let must_write = alt item.node { item_enum(_, _) { true } _ { false } };
|
let must_write = alt item.node { item_enum(_, _) { true } _ { false } };
|
||||||
if !must_write && !ecx.ccx.reachable.contains_key(item.id) { ret; }
|
if !must_write && !ecx.ccx.reachable.contains_key(item.id) { ret; }
|
||||||
|
|
||||||
|
fn add_to_index_(item: @item, ebml_w: ebml::writer,
|
||||||
|
index: @mutable [entry<int>]) {
|
||||||
*index += [{val: item.id, pos: ebml_w.writer.tell()}];
|
*index += [{val: item.id, pos: ebml_w.writer.tell()}];
|
||||||
|
}
|
||||||
|
let add_to_index = bind add_to_index_(item, ebml_w, index);
|
||||||
|
|
||||||
alt item.node {
|
alt item.node {
|
||||||
item_const(_, _) {
|
item_const(_, _) {
|
||||||
|
add_to_index();
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(item.id));
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
encode_family(ebml_w, 'c');
|
encode_family(ebml_w, 'c');
|
||||||
@@ -482,6 +483,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
item_fn(decl, tps, _) {
|
item_fn(decl, tps, _) {
|
||||||
|
add_to_index();
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(item.id));
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
encode_family(ebml_w, purity_fn_family(decl.purity));
|
encode_family(ebml_w, purity_fn_family(decl.purity));
|
||||||
@@ -496,9 +498,11 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
item_mod(m) {
|
item_mod(m) {
|
||||||
|
add_to_index();
|
||||||
encode_info_for_mod(ecx, ebml_w, m, item.id, path, item.ident);
|
encode_info_for_mod(ecx, ebml_w, m, item.id, path, item.ident);
|
||||||
}
|
}
|
||||||
item_native_mod(_) {
|
item_native_mod(_) {
|
||||||
|
add_to_index();
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(item.id));
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
encode_family(ebml_w, 'n');
|
encode_family(ebml_w, 'n');
|
||||||
@@ -507,6 +511,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
item_ty(_, tps) {
|
item_ty(_, tps) {
|
||||||
|
add_to_index();
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(item.id));
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
encode_family(ebml_w, 'y');
|
encode_family(ebml_w, 'y');
|
||||||
@@ -517,6 +522,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
item_enum(variants, tps) {
|
item_enum(variants, tps) {
|
||||||
|
add_to_index();
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(item.id));
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
encode_family(ebml_w, 't');
|
encode_family(ebml_w, 't');
|
||||||
@@ -533,15 +539,50 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
path, index, tps);
|
path, index, tps);
|
||||||
}
|
}
|
||||||
item_class(tps,items,ctor) {
|
item_class(tps,items,ctor) {
|
||||||
|
/* First, encode the fields and methods
|
||||||
|
These come first because we need to write them to make
|
||||||
|
the index, and the index needs to be in the item for the
|
||||||
|
class itself */
|
||||||
|
let idx = encode_info_for_class(ecx, ebml_w, item.id, path, items,
|
||||||
|
index);
|
||||||
|
/* Index the class*/
|
||||||
|
add_to_index();
|
||||||
|
/* Now, make an item for the class itself */
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
let idx = encode_info_for_class(ecx, ebml_w, item.id, path,
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
item.ident, tps, items);
|
encode_family(ebml_w, 'C');
|
||||||
/* each class must have its own index */
|
encode_type_param_bounds(ebml_w, ecx, tps);
|
||||||
|
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
|
||||||
|
encode_name(ebml_w, item.ident);
|
||||||
|
encode_path(ebml_w, path, ast_map::path_name(item.ident));
|
||||||
|
|
||||||
|
/* Encode def_ids for each field and method
|
||||||
|
for methods, write all the stuff get_iface_method
|
||||||
|
needs to know*/
|
||||||
|
let (fs,ms) = ast_util::split_class_items(items);
|
||||||
|
for f in fs {
|
||||||
|
ebml_w.start_tag(tag_item_field);
|
||||||
|
encode_family(ebml_w, 'g');
|
||||||
|
encode_name(ebml_w, f.ident);
|
||||||
|
encode_def_id(ebml_w, local_def(f.id));
|
||||||
|
ebml_w.end_tag();
|
||||||
|
}
|
||||||
|
for m in ms {
|
||||||
|
ebml_w.start_tag(tag_item_method);
|
||||||
|
#debug("Writing %s %d", m.ident, m.id);
|
||||||
|
encode_family(ebml_w, purity_fn_family(m.decl.purity));
|
||||||
|
encode_name(ebml_w, m.ident);
|
||||||
|
encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
|
||||||
|
encode_def_id(ebml_w, local_def(m.id));
|
||||||
|
ebml_w.end_tag();
|
||||||
|
}
|
||||||
|
/* Each class has its own index -- encode it */
|
||||||
let bkts = create_index(idx, hash_node_id);
|
let bkts = create_index(idx, hash_node_id);
|
||||||
encode_index(ebml_w, bkts, write_int);
|
encode_index(ebml_w, bkts, write_int);
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
item_res(_, tps, _, _, ctor_id) {
|
item_res(_, tps, _, _, ctor_id) {
|
||||||
|
add_to_index();
|
||||||
let fn_ty = node_id_to_type(tcx, ctor_id);
|
let fn_ty = node_id_to_type(tcx, ctor_id);
|
||||||
|
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
@@ -565,6 +606,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
item_impl(tps, ifce, _, methods) {
|
item_impl(tps, ifce, _, methods) {
|
||||||
|
add_to_index();
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(item.id));
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
encode_family(ebml_w, 'i');
|
encode_family(ebml_w, 'i');
|
||||||
@@ -598,6 +640,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
item_iface(tps, ms) {
|
item_iface(tps, ms) {
|
||||||
|
add_to_index();
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(item.id));
|
encode_def_id(ebml_w, local_def(item.id));
|
||||||
encode_family(ebml_w, 'I');
|
encode_family(ebml_w, 'I');
|
||||||
|
|||||||
@@ -2606,7 +2606,7 @@ fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
|
|||||||
name));
|
name));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
csearch::get_impl_method(cx.sess.cstore, did, name)
|
csearch::get_class_method(cx.sess.cstore, did, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
// xfail-test
|
|
||||||
// xfail-fast
|
// xfail-fast
|
||||||
// aux-build:cci_class_2.rs
|
// aux-build:cci_class_2.rs
|
||||||
use cci_class;
|
use cci_class_2;
|
||||||
import cci_class::kitties::*;
|
import cci_class_2::kitties::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let nyan : cat = cat(52u, 99);
|
let nyan : cat = cat(52u, 99);
|
||||||
|
|||||||
Reference in New Issue
Block a user