Rather than storing a list of ty::method per trait, store one ty::method
per method and list of def-ids per trait.
This commit is contained in:
parent
d94830830f
commit
007abe9352
@ -102,6 +102,7 @@ impl items contain tag_item_impl_method elements, and classes
|
|||||||
pub static tag_item_trait_method_self_ty: uint = 0x4b;
|
pub static tag_item_trait_method_self_ty: uint = 0x4b;
|
||||||
pub static tag_item_trait_method_self_ty_region: uint = 0x4c;
|
pub static tag_item_trait_method_self_ty_region: uint = 0x4c;
|
||||||
|
|
||||||
|
|
||||||
// Reexports are found within module tags. Each reexport contains def_ids
|
// Reexports are found within module tags. Each reexport contains def_ids
|
||||||
// and names.
|
// and names.
|
||||||
pub static tag_items_data_item_reexport: uint = 0x4d;
|
pub static tag_items_data_item_reexport: uint = 0x4d;
|
||||||
@ -159,6 +160,9 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f
|
|||||||
pub static tag_link_args: uint = 0x79;
|
pub static tag_link_args: uint = 0x79;
|
||||||
pub static tag_link_args_arg: uint = 0x7a;
|
pub static tag_link_args_arg: uint = 0x7a;
|
||||||
|
|
||||||
|
pub static tag_item_method_tps: uint = 0x7b;
|
||||||
|
pub static tag_item_method_fty: uint = 0x7c;
|
||||||
|
|
||||||
pub struct LinkMeta {
|
pub struct LinkMeta {
|
||||||
name: @str,
|
name: @str,
|
||||||
vers: @str,
|
vers: @str,
|
||||||
|
@ -111,12 +111,24 @@ pub fn get_impls_for_mod(cstore: @mut cstore::CStore, def: ast::def_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_trait_methods(tcx: ty::ctxt,
|
pub fn get_method(tcx: ty::ctxt,
|
||||||
def: ast::def_id)
|
def: ast::def_id) -> ty::method
|
||||||
-> @~[ty::method] {
|
{
|
||||||
let cstore = tcx.cstore;
|
let cdata = cstore::get_crate_data(tcx.cstore, def.crate);
|
||||||
|
decoder::get_method(tcx.cstore.intr, cdata, def.node, tcx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_method_name_and_self_ty(cstore: @mut cstore::CStore,
|
||||||
|
def: ast::def_id) -> (ast::ident, ast::self_ty_)
|
||||||
|
{
|
||||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||||
decoder::get_trait_methods(cstore.intr, cdata, def.node, tcx)
|
decoder::get_method_name_and_self_ty(cstore.intr, cdata, def.node)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_trait_method_def_ids(cstore: @mut cstore::CStore,
|
||||||
|
def: ast::def_id) -> ~[ast::def_id] {
|
||||||
|
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||||
|
decoder::get_trait_method_def_ids(cdata, def.node)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_provided_trait_methods(tcx: ty::ctxt,
|
pub fn get_provided_trait_methods(tcx: ty::ctxt,
|
||||||
@ -133,13 +145,6 @@ pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] {
|
|||||||
decoder::get_supertraits(cdata, def.node, tcx)
|
decoder::get_supertraits(cdata, def.node, tcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_method_names_if_trait(cstore: @mut cstore::CStore,
|
|
||||||
def: ast::def_id)
|
|
||||||
-> Option<~[(ast::ident, ast::self_ty_)]> {
|
|
||||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
|
||||||
return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_type_name_if_impl(cstore: @mut cstore::CStore, def: ast::def_id)
|
pub fn get_type_name_if_impl(cstore: @mut cstore::CStore, def: ast::def_id)
|
||||||
-> Option<ast::ident> {
|
-> Option<ast::ident> {
|
||||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
use metadata::csearch;
|
use metadata::csearch;
|
||||||
use metadata::cstore;
|
use metadata::cstore;
|
||||||
use metadata::decoder;
|
use metadata::decoder;
|
||||||
use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data};
|
use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
|
||||||
|
parse_bare_fn_ty_data};
|
||||||
use middle::{ty, resolve};
|
use middle::{ty, resolve};
|
||||||
|
|
||||||
use core::hash::HashUtil;
|
use core::hash::HashUtil;
|
||||||
@ -229,6 +230,12 @@ fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
|
|||||||
|_, did| translate_def_id(cdata, did))
|
|_, did| translate_def_id(cdata, did))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy {
|
||||||
|
let tp = reader::get_doc(doc, tag_item_method_fty);
|
||||||
|
parse_bare_fn_ty_data(tp.data, cdata.cnum, tp.start, tcx,
|
||||||
|
|_, did| translate_def_id(cdata, did))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
|
pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
|
||||||
tcx: ty::ctxt, cdata: cmd) -> ty::t {
|
tcx: ty::ctxt, cdata: cmd) -> ty::t {
|
||||||
let t = doc_type(item, tcx, cdata);
|
let t = doc_type(item, tcx, cdata);
|
||||||
@ -247,10 +254,11 @@ fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] {
|
|||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd)
|
fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd,
|
||||||
|
tag: uint)
|
||||||
-> @~[ty::param_bounds] {
|
-> @~[ty::param_bounds] {
|
||||||
let mut bounds = ~[];
|
let mut bounds = ~[];
|
||||||
for reader::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| {
|
for reader::tagged_docs(item, tag) |p| {
|
||||||
let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx,
|
let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx,
|
||||||
|_, did| translate_def_id(cdata, did));
|
|_, did| translate_def_id(cdata, did));
|
||||||
bounds.push(bd);
|
bounds.push(bd);
|
||||||
@ -338,7 +346,8 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
|
|||||||
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
|
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
|
||||||
dl_def(ast::def_variant(enum_did, did))
|
dl_def(ast::def_variant(enum_did, did))
|
||||||
}
|
}
|
||||||
Trait | Enum => dl_def(ast::def_ty(did)),
|
Trait => dl_def(ast::def_trait(did)),
|
||||||
|
Enum => dl_def(ast::def_ty(did)),
|
||||||
Impl => dl_impl(did),
|
Impl => dl_impl(did),
|
||||||
PublicField | PrivateField | InheritedField => dl_field,
|
PublicField | PrivateField | InheritedField => dl_field,
|
||||||
}
|
}
|
||||||
@ -359,7 +368,7 @@ pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
|||||||
let t = item_type(ast::def_id { crate: cdata.cnum, node: id }, item, tcx,
|
let t = item_type(ast::def_id { crate: cdata.cnum, node: id }, item, tcx,
|
||||||
cdata);
|
cdata);
|
||||||
let tp_bounds = if family_has_type_params(item_family(item)) {
|
let tp_bounds = if family_has_type_params(item_family(item)) {
|
||||||
item_ty_param_bounds(item, tcx, cdata)
|
item_ty_param_bounds(item, tcx, cdata, tag_items_data_item_ty_param_bounds)
|
||||||
} else { @~[] };
|
} else { @~[] };
|
||||||
let rp = item_ty_region_param(item);
|
let rp = item_ty_region_param(item);
|
||||||
ty::ty_param_bounds_and_ty {
|
ty::ty_param_bounds_and_ty {
|
||||||
@ -690,36 +699,46 @@ pub fn get_impls_for_mod(intr: @ident_interner,
|
|||||||
@result
|
@result
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Works for both classes and traits */
|
pub fn get_method_name_and_self_ty(
|
||||||
pub fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
intr: @ident_interner,
|
||||||
tcx: ty::ctxt) -> @~[ty::method] {
|
cdata: cmd,
|
||||||
|
id: ast::node_id) -> (ast::ident, ast::self_ty_)
|
||||||
|
{
|
||||||
|
let method_doc = lookup_item(id, cdata.data);
|
||||||
|
let name = item_name(intr, method_doc);
|
||||||
|
let self_ty = get_self_ty(method_doc);
|
||||||
|
(name, self_ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
||||||
|
tcx: ty::ctxt) -> ty::method
|
||||||
|
{
|
||||||
|
let method_doc = lookup_item(id, cdata.data);
|
||||||
|
let bounds = item_ty_param_bounds(method_doc, tcx, cdata,
|
||||||
|
tag_item_method_tps);
|
||||||
|
let name = item_name(intr, method_doc);
|
||||||
|
let def_id = item_def_id(method_doc, cdata);
|
||||||
|
let fty = doc_method_fty(method_doc, tcx, cdata);
|
||||||
|
let self_ty = get_self_ty(method_doc);
|
||||||
|
ty::method {
|
||||||
|
ident: name,
|
||||||
|
tps: bounds,
|
||||||
|
fty: fty,
|
||||||
|
self_ty: self_ty,
|
||||||
|
vis: ast::public,
|
||||||
|
def_id: def_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_trait_method_def_ids(cdata: cmd,
|
||||||
|
id: ast::node_id) -> ~[ast::def_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 = ~[];
|
||||||
for reader::tagged_docs(item, tag_item_trait_method) |mth| {
|
for reader::tagged_docs(item, tag_item_trait_method) |mth| {
|
||||||
let bounds = item_ty_param_bounds(mth, tcx, cdata);
|
result.push(item_def_id(mth, cdata));
|
||||||
let name = item_name(intr, mth);
|
|
||||||
let ty = doc_type(mth, tcx, cdata);
|
|
||||||
let def_id = item_def_id(mth, cdata);
|
|
||||||
let fty = match ty::get(ty).sty {
|
|
||||||
ty::ty_bare_fn(ref f) => copy *f,
|
|
||||||
_ => {
|
|
||||||
tcx.diag.handler().bug(
|
|
||||||
~"get_trait_methods: id has non-function type");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let self_ty = get_self_ty(mth);
|
|
||||||
result.push(ty::method {
|
|
||||||
ident: name,
|
|
||||||
tps: bounds,
|
|
||||||
fty: fty,
|
|
||||||
self_ty: self_ty,
|
|
||||||
vis: ast::public,
|
|
||||||
def_id: def_id
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
debug!("get_trait_methods: }");
|
result
|
||||||
@result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
|
pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
|
||||||
@ -734,7 +753,8 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
|
|||||||
|
|
||||||
let did = item_def_id(mth, cdata);
|
let did = item_def_id(mth, cdata);
|
||||||
|
|
||||||
let bounds = item_ty_param_bounds(mth, tcx, cdata);
|
let bounds = item_ty_param_bounds(mth, tcx, cdata,
|
||||||
|
tag_items_data_item_ty_param_bounds);
|
||||||
let name = item_name(intr, mth);
|
let name = item_name(intr, mth);
|
||||||
let ty = doc_type(mth, tcx, cdata);
|
let ty = doc_type(mth, tcx, cdata);
|
||||||
|
|
||||||
@ -777,26 +797,6 @@ pub fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the item in question is a trait, returns its set of methods and
|
|
||||||
// their self types. Otherwise, returns none. This overlaps in an
|
|
||||||
// annoying way with get_trait_methods.
|
|
||||||
pub fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd,
|
|
||||||
node_id: ast::node_id)
|
|
||||||
-> Option<~[(ast::ident, ast::self_ty_)]> {
|
|
||||||
|
|
||||||
let item = lookup_item(node_id, cdata.data);
|
|
||||||
if item_family(item) != Trait {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut resulting_methods = ~[];
|
|
||||||
for reader::tagged_docs(item, tag_item_trait_method) |method| {
|
|
||||||
resulting_methods.push(
|
|
||||||
(item_name(intr, method), get_self_ty(method)));
|
|
||||||
}
|
|
||||||
return Some(resulting_methods);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_type_name_if_impl(intr: @ident_interner,
|
pub fn get_type_name_if_impl(intr: @ident_interner,
|
||||||
cdata: cmd,
|
cdata: cmd,
|
||||||
node_id: ast::node_id) -> Option<ast::ident> {
|
node_id: ast::node_id) -> Option<ast::ident> {
|
||||||
|
@ -170,8 +170,10 @@ fn encode_family(ebml_w: writer::Encoder, c: char) {
|
|||||||
|
|
||||||
pub fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) }
|
pub fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) }
|
||||||
|
|
||||||
fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext,
|
fn encode_ty_type_param_bounds(ebml_w: writer::Encoder,
|
||||||
params: @~[ty::param_bounds]) {
|
ecx: @EncodeContext,
|
||||||
|
params: @~[ty::param_bounds],
|
||||||
|
tag: uint) {
|
||||||
let ty_str_ctxt = @tyencode::ctxt {
|
let ty_str_ctxt = @tyencode::ctxt {
|
||||||
diag: ecx.diag,
|
diag: ecx.diag,
|
||||||
ds: def_to_str,
|
ds: def_to_str,
|
||||||
@ -179,7 +181,7 @@ fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext,
|
|||||||
reachable: |a| reachable(ecx, a),
|
reachable: |a| reachable(ecx, a),
|
||||||
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
|
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
|
||||||
for params.each |param| {
|
for params.each |param| {
|
||||||
ebml_w.start_tag(tag_items_data_item_ty_param_bounds);
|
ebml_w.start_tag(tag);
|
||||||
tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param);
|
tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param);
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
@ -190,7 +192,8 @@ fn encode_type_param_bounds(ebml_w: writer::Encoder,
|
|||||||
params: &OptVec<TyParam>) {
|
params: &OptVec<TyParam>) {
|
||||||
let ty_param_bounds =
|
let ty_param_bounds =
|
||||||
@params.map_to_vec(|param| *ecx.tcx.ty_param_bounds.get(¶m.id));
|
@params.map_to_vec(|param| *ecx.tcx.ty_param_bounds.get(¶m.id));
|
||||||
encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds);
|
encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds,
|
||||||
|
tag_items_data_item_ty_param_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -227,6 +230,23 @@ fn encode_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) {
|
|||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_method_fty(ecx: @EncodeContext,
|
||||||
|
ebml_w: writer::Encoder,
|
||||||
|
typ: &ty::BareFnTy)
|
||||||
|
{
|
||||||
|
ebml_w.start_tag(tag_item_method_fty);
|
||||||
|
|
||||||
|
let ty_str_ctxt = @tyencode::ctxt {
|
||||||
|
diag: ecx.diag,
|
||||||
|
ds: def_to_str,
|
||||||
|
tcx: ecx.tcx,
|
||||||
|
reachable: |a| reachable(ecx, a),
|
||||||
|
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
|
||||||
|
tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
|
||||||
|
|
||||||
|
ebml_w.end_tag();
|
||||||
|
}
|
||||||
|
|
||||||
fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) {
|
fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) {
|
||||||
ebml_w.start_tag(tag_items_data_item_symbol);
|
ebml_w.start_tag(tag_items_data_item_symbol);
|
||||||
match ecx.item_symbols.find(&id) {
|
match ecx.item_symbols.find(&id) {
|
||||||
@ -868,8 +888,6 @@ fn add_to_index_(item: @item, ebml_w: writer::Encoder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
item_trait(ref generics, ref traits, ref ms) => {
|
item_trait(ref generics, ref traits, ref ms) => {
|
||||||
let mut provided_methods = ~[];
|
|
||||||
|
|
||||||
add_to_index();
|
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));
|
||||||
@ -879,97 +897,90 @@ fn add_to_index_(item: @item, ebml_w: writer::Encoder,
|
|||||||
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
|
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
|
||||||
encode_name(ecx, ebml_w, item.ident);
|
encode_name(ecx, ebml_w, item.ident);
|
||||||
encode_attributes(ebml_w, item.attrs);
|
encode_attributes(ebml_w, item.attrs);
|
||||||
let mut i = 0u;
|
for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| {
|
||||||
for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| {
|
ebml_w.start_tag(tag_item_trait_method);
|
||||||
match (*ms)[i] {
|
encode_def_id(ebml_w, method_def_id);
|
||||||
required(ref ty_m) => {
|
ebml_w.end_tag();
|
||||||
ebml_w.start_tag(tag_item_trait_method);
|
|
||||||
encode_def_id(ebml_w, local_def((*ty_m).id));
|
|
||||||
encode_name(ecx, ebml_w, mty.ident);
|
|
||||||
encode_type_param_bounds(ebml_w, ecx,
|
|
||||||
&ty_m.generics.ty_params);
|
|
||||||
encode_type(ecx, ebml_w,
|
|
||||||
ty::mk_bare_fn(tcx, copy mty.fty));
|
|
||||||
encode_family(ebml_w, purity_fn_family(mty.fty.purity));
|
|
||||||
encode_self_type(ebml_w, mty.self_ty);
|
|
||||||
encode_method_sort(ebml_w, 'r');
|
|
||||||
encode_visibility(ebml_w, ast::public);
|
|
||||||
ebml_w.end_tag();
|
|
||||||
}
|
|
||||||
provided(m) => {
|
|
||||||
provided_methods.push(m);
|
|
||||||
|
|
||||||
ebml_w.start_tag(tag_item_trait_method);
|
|
||||||
encode_def_id(ebml_w, local_def(m.id));
|
|
||||||
encode_name(ecx, ebml_w, mty.ident);
|
|
||||||
encode_type_param_bounds(ebml_w, ecx,
|
|
||||||
&m.generics.ty_params);
|
|
||||||
encode_type(ecx, ebml_w,
|
|
||||||
ty::mk_bare_fn(tcx, copy mty.fty));
|
|
||||||
encode_family(ebml_w, purity_fn_family(mty.fty.purity));
|
|
||||||
encode_self_type(ebml_w, mty.self_ty);
|
|
||||||
encode_method_sort(ebml_w, 'p');
|
|
||||||
encode_visibility(ebml_w, m.vis);
|
|
||||||
ebml_w.end_tag();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
||||||
for traits.each |associated_trait| {
|
for traits.each |associated_trait| {
|
||||||
encode_trait_ref(ebml_w, ecx, *associated_trait)
|
encode_trait_ref(ebml_w, ecx, *associated_trait);
|
||||||
}
|
}
|
||||||
|
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
|
|
||||||
// Now, output all of the static methods as items. Note that for the
|
// Now output the method info for each method.
|
||||||
// method info, we output static methods with type signatures as
|
//
|
||||||
// written. Here, we output the *real* type signatures. I feel like
|
// Note: for the moment, the data structures here are *slightly*
|
||||||
// maybe we should only ever handle the real type signatures.
|
// different from those expected by `encode_info_for_method()`,
|
||||||
for ms.each |m| {
|
// but I do plan to refactor this later in this patch to avoid the
|
||||||
let ty_m = ast_util::trait_method_to_ty_method(m);
|
// duplication.
|
||||||
if ty_m.self_ty.node != ast::sty_static { loop; }
|
for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| {
|
||||||
|
assert!(method_def_id.crate == ast::local_crate);
|
||||||
|
|
||||||
index.push(entry { val: ty_m.id, pos: ebml_w.writer.tell() });
|
let method_ty: @ty::method = ty::method(tcx, method_def_id);
|
||||||
|
|
||||||
|
index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()});
|
||||||
|
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
encode_def_id(ebml_w, local_def(ty_m.id));
|
|
||||||
encode_parent_item(ebml_w, local_def(item.id));
|
|
||||||
encode_name(ecx, ebml_w, ty_m.ident);
|
|
||||||
encode_family(ebml_w,
|
|
||||||
purity_static_method_family(ty_m.purity));
|
|
||||||
let polyty = ecx.tcx.tcache.get(&local_def(ty_m.id));
|
|
||||||
encode_ty_type_param_bounds(ebml_w, ecx, polyty.bounds);
|
|
||||||
encode_type(ecx, ebml_w, polyty.ty);
|
|
||||||
let mut m_path = vec::append(~[], path); // :-(
|
|
||||||
m_path += [ast_map::path_name(item.ident)];
|
|
||||||
encode_path(ecx, ebml_w, m_path, ast_map::path_name(ty_m.ident));
|
|
||||||
|
|
||||||
// For now, use the item visibility until trait methods can have
|
encode_def_id(ebml_w, method_def_id);
|
||||||
// real visibility in the AST.
|
encode_parent_item(ebml_w, local_def(item.id));
|
||||||
encode_visibility(ebml_w, item.vis);
|
encode_name(ecx, ebml_w, method_ty.ident);
|
||||||
|
|
||||||
|
match method_ty.self_ty {
|
||||||
|
sty_static => {
|
||||||
|
encode_family(ebml_w,
|
||||||
|
purity_static_method_family(
|
||||||
|
method_ty.fty.purity));
|
||||||
|
|
||||||
|
let tpt = ty::lookup_item_type(tcx, method_def_id);
|
||||||
|
encode_ty_type_param_bounds(ebml_w, ecx, tpt.bounds,
|
||||||
|
tag_items_data_item_ty_param_bounds);
|
||||||
|
encode_type(ecx, ebml_w, tpt.ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
encode_family(ebml_w,
|
||||||
|
purity_fn_family(
|
||||||
|
method_ty.fty.purity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps,
|
||||||
|
tag_item_method_tps);
|
||||||
|
encode_method_fty(ecx, ebml_w, &method_ty.fty);
|
||||||
|
encode_visibility(ebml_w, method_ty.vis);
|
||||||
|
encode_self_type(ebml_w, method_ty.self_ty);
|
||||||
|
let mut trait_path = vec::append(~[], path);
|
||||||
|
trait_path.push(ast_map::path_name(item.ident));
|
||||||
|
encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
|
||||||
|
|
||||||
|
match ms[i] {
|
||||||
|
required(_) => {
|
||||||
|
encode_method_sort(ebml_w, 'r');
|
||||||
|
}
|
||||||
|
|
||||||
|
provided(m) => {
|
||||||
|
// This is obviously a bogus assert but I don't think this
|
||||||
|
// ever worked before anyhow...near as I can tell, before
|
||||||
|
// we would emit two items.
|
||||||
|
if method_ty.self_ty == sty_static {
|
||||||
|
tcx.sess.span_unimpl(
|
||||||
|
item.span,
|
||||||
|
fmt!("Method %s is both provided and static",
|
||||||
|
*tcx.sess.intr().get(method_ty.ident)));
|
||||||
|
}
|
||||||
|
encode_type_param_bounds(ebml_w, ecx,
|
||||||
|
&m.generics.ty_params);
|
||||||
|
encode_method_sort(ebml_w, 'p');
|
||||||
|
(ecx.encode_inlined_item)(
|
||||||
|
ecx, ebml_w, path,
|
||||||
|
ii_method(local_def(item.id), m));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, output all the provided methods as items.
|
|
||||||
for provided_methods.each |m| {
|
|
||||||
index.push(entry { val: m.id, pos: ebml_w.writer.tell() });
|
|
||||||
|
|
||||||
// We do not concatenate the generics of the owning impl and that
|
|
||||||
// of provided methods. I am not sure why this is. -ndm
|
|
||||||
let owner_generics = ast_util::empty_generics();
|
|
||||||
|
|
||||||
encode_info_for_method(ecx,
|
|
||||||
ebml_w,
|
|
||||||
/*bad*/copy path,
|
|
||||||
true,
|
|
||||||
item.id,
|
|
||||||
*m,
|
|
||||||
item.vis,
|
|
||||||
&owner_generics,
|
|
||||||
&m.generics);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
item_mac(*) => fail!(~"item macros unimplemented")
|
item_mac(*) => fail!(~"item macros unimplemented")
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,12 @@ pub fn parse_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
|
|||||||
parse_ty(st, conv)
|
parse_ty(st, conv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_bare_fn_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
|
||||||
|
conv: conv_did) -> ty::BareFnTy {
|
||||||
|
let st = parse_state_from_data(data, crate_num, pos, tcx);
|
||||||
|
parse_bare_fn_ty(st, conv)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
|
pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
|
||||||
conv: conv_did) -> ty::arg {
|
conv: conv_did) -> ty::arg {
|
||||||
let st = parse_state_from_data(data, crate_num, pos, tcx);
|
let st = parse_state_from_data(data, crate_num, pos, tcx);
|
||||||
|
@ -384,7 +384,7 @@ fn enc_onceness(w: @io::Writer, o: Onceness) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
|
pub fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
|
||||||
enc_purity(w, ft.purity);
|
enc_purity(w, ft.purity);
|
||||||
enc_abi_set(w, ft.abis);
|
enc_abi_set(w, ft.abis);
|
||||||
enc_fn_sig(w, cx, &ft.sig);
|
enc_fn_sig(w, cx, &ft.sig);
|
||||||
|
@ -417,6 +417,7 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::def {
|
|||||||
ast::def_variant(e_did, v_did) => {
|
ast::def_variant(e_did, v_did) => {
|
||||||
ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
|
ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
|
||||||
}
|
}
|
||||||
|
ast::def_trait(did) => ast::def_trait(did.tr(xcx)),
|
||||||
ast::def_ty(did) => ast::def_ty(did.tr(xcx)),
|
ast::def_ty(did) => ast::def_ty(did.tr(xcx)),
|
||||||
ast::def_prim_ty(p) => ast::def_prim_ty(p),
|
ast::def_prim_ty(p) => ast::def_prim_ty(p),
|
||||||
ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v),
|
ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v),
|
||||||
|
@ -462,7 +462,7 @@ fn cat_def(&self,
|
|||||||
ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) |
|
ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) |
|
||||||
ast::def_foreign_mod(_) | ast::def_const(_) |
|
ast::def_foreign_mod(_) | ast::def_const(_) |
|
||||||
ast::def_use(_) | ast::def_variant(*) |
|
ast::def_use(_) | ast::def_variant(*) |
|
||||||
ast::def_ty(_) | ast::def_prim_ty(_) |
|
ast::def_trait(_) | ast::def_ty(_) | ast::def_prim_ty(_) |
|
||||||
ast::def_ty_param(*) | ast::def_struct(*) |
|
ast::def_ty_param(*) | ast::def_struct(*) |
|
||||||
ast::def_typaram_binder(*) | ast::def_region(_) |
|
ast::def_typaram_binder(*) | ast::def_region(_) |
|
||||||
ast::def_label(_) | ast::def_self_ty(*) => {
|
ast::def_label(_) | ast::def_self_ty(*) => {
|
||||||
|
@ -211,7 +211,7 @@ struct Foo { a: int, b: ~int }
|
|||||||
use middle::pat_util::{pat_bindings};
|
use middle::pat_util::{pat_bindings};
|
||||||
use middle::freevars;
|
use middle::freevars;
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::typeck::method_map;
|
use middle::typeck::{method_map, method_map_entry};
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
|
|
||||||
|
@ -690,7 +690,9 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
|
|||||||
match ty.node {
|
match ty.node {
|
||||||
ast::ty_path(path, id) => {
|
ast::ty_path(path, id) => {
|
||||||
match cx.def_map.find(&id) {
|
match cx.def_map.find(&id) {
|
||||||
Some(&ast::def_ty(did)) | Some(&ast::def_struct(did)) => {
|
Some(&ast::def_ty(did)) |
|
||||||
|
Some(&ast::def_trait(did)) |
|
||||||
|
Some(&ast::def_struct(did)) => {
|
||||||
if did.crate == ast::local_crate {
|
if did.crate == ast::local_crate {
|
||||||
if cx.region_is_relevant(path.rp) {
|
if cx.region_is_relevant(path.rp) {
|
||||||
cx.add_dep(did.node);
|
cx.add_dep(did.node);
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use metadata::csearch::{each_path, get_method_names_if_trait};
|
use metadata::csearch::{each_path, get_trait_method_def_ids};
|
||||||
|
use metadata::csearch::get_method_name_and_self_ty;
|
||||||
use metadata::csearch::get_static_methods_if_impl;
|
use metadata::csearch::get_static_methods_if_impl;
|
||||||
use metadata::csearch::get_type_name_if_impl;
|
use metadata::csearch::get_type_name_if_impl;
|
||||||
use metadata::cstore::find_extern_mod_stmt_cnum;
|
use metadata::cstore::find_extern_mod_stmt_cnum;
|
||||||
@ -31,7 +32,7 @@
|
|||||||
use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label};
|
use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label};
|
||||||
use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self};
|
use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self};
|
||||||
use syntax::ast::{def_self_ty, def_static_method, def_struct, def_ty};
|
use syntax::ast::{def_self_ty, def_static_method, def_struct, def_ty};
|
||||||
use syntax::ast::{def_ty_param, def_typaram_binder};
|
use syntax::ast::{def_ty_param, def_typaram_binder, def_trait};
|
||||||
use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
|
use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
|
||||||
use syntax::ast::{expr_binary, expr_break, expr_field};
|
use syntax::ast::{expr_binary, expr_break, expr_field};
|
||||||
use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path};
|
use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path};
|
||||||
@ -1341,7 +1342,7 @@ fn build_reduced_graph_for_item(@mut self,
|
|||||||
let def_id = local_def(item.id);
|
let def_id = local_def(item.id);
|
||||||
self.trait_info.insert(def_id, method_names);
|
self.trait_info.insert(def_id, method_names);
|
||||||
|
|
||||||
name_bindings.define_type(privacy, def_ty(def_id), sp);
|
name_bindings.define_type(privacy, def_trait(def_id), sp);
|
||||||
visit_item(item, new_parent, visitor);
|
visit_item(item, new_parent, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1611,36 +1612,40 @@ fn handle_external_def(@mut self,
|
|||||||
crate) building value %s", final_ident);
|
crate) building value %s", final_ident);
|
||||||
child_name_bindings.define_value(Public, def, dummy_sp());
|
child_name_bindings.define_value(Public, def, dummy_sp());
|
||||||
}
|
}
|
||||||
def_ty(def_id) => {
|
def_trait(def_id) => {
|
||||||
debug!("(building reduced graph for external \
|
debug!("(building reduced graph for external \
|
||||||
crate) building type %s", final_ident);
|
crate) building type %s", final_ident);
|
||||||
|
|
||||||
// If this is a trait, add all the method names
|
// If this is a trait, add all the method names
|
||||||
// to the trait info.
|
// to the trait info.
|
||||||
|
|
||||||
match get_method_names_if_trait(self.session.cstore, def_id) {
|
let method_def_ids = get_trait_method_def_ids(self.session.cstore,
|
||||||
None => {
|
def_id);
|
||||||
// Nothing to do.
|
let mut interned_method_names = HashSet::new();
|
||||||
|
for method_def_ids.each |&method_def_id| {
|
||||||
|
let (method_name, self_ty) =
|
||||||
|
get_method_name_and_self_ty(self.session.cstore,
|
||||||
|
method_def_id);
|
||||||
|
|
||||||
|
debug!("(building reduced graph for \
|
||||||
|
external crate) ... adding \
|
||||||
|
trait method '%s'",
|
||||||
|
*self.session.str_of(method_name));
|
||||||
|
|
||||||
|
// Add it to the trait info if not static.
|
||||||
|
if self_ty != sty_static {
|
||||||
|
interned_method_names.insert(method_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(method_names) => {
|
self.trait_info.insert(def_id, interned_method_names);
|
||||||
let mut interned_method_names = HashSet::new();
|
|
||||||
for method_names.each |method_data| {
|
|
||||||
let (method_name, self_ty) = *method_data;
|
|
||||||
debug!("(building reduced graph for \
|
|
||||||
external crate) ... adding \
|
|
||||||
trait method '%s'",
|
|
||||||
*self.session.str_of(method_name));
|
|
||||||
|
|
||||||
// Add it to the trait info if not static.
|
child_name_bindings.define_type(Public, def, dummy_sp());
|
||||||
if self_ty != sty_static {
|
}
|
||||||
interned_method_names.insert(method_name);
|
def_ty(_) => {
|
||||||
}
|
debug!("(building reduced graph for external \
|
||||||
}
|
crate) building type %s", final_ident);
|
||||||
self.trait_info.insert(def_id, interned_method_names);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
child_name_bindings.define_type(Public, def, dummy_sp());
|
child_name_bindings.define_type(Public, def, dummy_sp());
|
||||||
}
|
}
|
||||||
def_struct(def_id) => {
|
def_struct(def_id) => {
|
||||||
debug!("(building reduced graph for external \
|
debug!("(building reduced graph for external \
|
||||||
@ -4952,7 +4957,7 @@ fn search_for_traits_containing_method(@mut self,
|
|||||||
match child_name_bindings.def_for_namespace(TypeNS) {
|
match child_name_bindings.def_for_namespace(TypeNS) {
|
||||||
Some(def) => {
|
Some(def) => {
|
||||||
match def {
|
match def {
|
||||||
def_ty(trait_def_id) => {
|
def_trait(trait_def_id) => {
|
||||||
self.add_trait_info_if_containing_method(
|
self.add_trait_info_if_containing_method(
|
||||||
&mut found_traits, trait_def_id, name);
|
&mut found_traits, trait_def_id, name);
|
||||||
}
|
}
|
||||||
@ -4979,7 +4984,7 @@ fn search_for_traits_containing_method(@mut self,
|
|||||||
match target.bindings.def_for_namespace(TypeNS) {
|
match target.bindings.def_for_namespace(TypeNS) {
|
||||||
Some(def) => {
|
Some(def) => {
|
||||||
match def {
|
match def {
|
||||||
def_ty(trait_def_id) => {
|
def_trait(trait_def_id) => {
|
||||||
let added = self.
|
let added = self.
|
||||||
add_trait_info_if_containing_method(
|
add_trait_info_if_containing_method(
|
||||||
&mut found_traits,
|
&mut found_traits,
|
||||||
|
@ -148,7 +148,7 @@ fn trans_def(bcx: block, def: ast::def, ref_expr: @ast::expr) -> Callee {
|
|||||||
ast::def_self(*) => {
|
ast::def_self(*) => {
|
||||||
datum_callee(bcx, ref_expr)
|
datum_callee(bcx, ref_expr)
|
||||||
}
|
}
|
||||||
ast::def_mod(*) | ast::def_foreign_mod(*) |
|
ast::def_mod(*) | ast::def_foreign_mod(*) | ast::def_trait(*) |
|
||||||
ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) |
|
ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) |
|
||||||
ast::def_use(*) | ast::def_typaram_binder(*) |
|
ast::def_use(*) | ast::def_typaram_binder(*) |
|
||||||
ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) |
|
ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) |
|
||||||
|
@ -174,6 +174,7 @@ pub fn trans_method_callee(bcx: block,
|
|||||||
mentry: typeck::method_map_entry)
|
mentry: typeck::method_map_entry)
|
||||||
-> Callee {
|
-> Callee {
|
||||||
let _icx = bcx.insn_ctxt("impl::trans_method_callee");
|
let _icx = bcx.insn_ctxt("impl::trans_method_callee");
|
||||||
|
let tcx = bcx.tcx();
|
||||||
|
|
||||||
debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%?)",
|
debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%?)",
|
||||||
callee_id, bcx.expr_to_str(self), mentry);
|
callee_id, bcx.expr_to_str(self), mentry);
|
||||||
@ -189,33 +190,33 @@ pub fn trans_method_callee(bcx: block,
|
|||||||
|
|
||||||
// Get the ID of the method we're calling.
|
// Get the ID of the method we're calling.
|
||||||
let method_name =
|
let method_name =
|
||||||
ty::trait_methods(bcx.tcx(), trait_id)[method_index].ident;
|
ty::trait_method(tcx, trait_id, method_index).ident;
|
||||||
let method_id = method_with_name(bcx.ccx(), impl_def_id,
|
let method_id =
|
||||||
method_name);
|
method_with_name(bcx.ccx(), impl_def_id, method_name);
|
||||||
origin = typeck::method_static(method_id);
|
origin = typeck::method_static(method_id);
|
||||||
}
|
}
|
||||||
typeck::method_super(trait_id, method_index) => {
|
typeck::method_super(trait_id, method_index) => {
|
||||||
// <self_ty> is the self type for this method call
|
// <self_ty> is the self type for this method call
|
||||||
let self_ty = node_id_type(bcx, self.id);
|
let self_ty = node_id_type(bcx, self.id);
|
||||||
let tcx = bcx.tcx();
|
|
||||||
// <impl_id> is the ID of the implementation of
|
// <impl_id> is the ID of the implementation of
|
||||||
// trait <trait_id> for type <self_ty>
|
// trait <trait_id> for type <self_ty>
|
||||||
let impl_id = ty::get_impl_id(tcx, trait_id, self_ty);
|
let impl_id = ty::get_impl_id(tcx, trait_id, self_ty);
|
||||||
// Get the supertrait's methods
|
// Get the supertrait's methods
|
||||||
let supertrait_methods = ty::trait_methods(tcx, trait_id);
|
let supertrait_method_def_ids = ty::trait_method_def_ids(tcx, trait_id);
|
||||||
// Make sure to fail with a readable error message if
|
// Make sure to fail with a readable error message if
|
||||||
// there's some internal error here
|
// there's some internal error here
|
||||||
if !(method_index < supertrait_methods.len()) {
|
if !(method_index < supertrait_method_def_ids.len()) {
|
||||||
tcx.sess.bug(~"trans_method_callee: supertrait method \
|
tcx.sess.bug(~"trans_method_callee: supertrait method \
|
||||||
index is out of bounds");
|
index is out of bounds");
|
||||||
}
|
}
|
||||||
// Get the method name using the method index in the origin
|
// Get the method name using the method index in the origin
|
||||||
let method_name = supertrait_methods[method_index].ident;
|
let method_name =
|
||||||
|
ty::method(tcx, supertrait_method_def_ids[method_index]).ident;
|
||||||
// Now that we know the impl ID, we can look up the method
|
// Now that we know the impl ID, we can look up the method
|
||||||
// ID from its name
|
// ID from its name
|
||||||
origin = typeck::method_static(method_with_name(bcx.ccx(),
|
origin = typeck::method_static(method_with_name(bcx.ccx(),
|
||||||
impl_id,
|
impl_id,
|
||||||
method_name));
|
method_name));
|
||||||
}
|
}
|
||||||
typeck::method_static(*) | typeck::method_param(*) |
|
typeck::method_static(*) | typeck::method_param(*) |
|
||||||
typeck::method_trait(*) => {}
|
typeck::method_trait(*) => {}
|
||||||
@ -448,7 +449,7 @@ pub fn trans_monomorphized_callee(bcx: block,
|
|||||||
return match vtbl {
|
return match vtbl {
|
||||||
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
let mname = ty::trait_methods(ccx.tcx, trait_id)[n_method].ident;
|
let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
|
||||||
let mth_id = method_with_name_or_default(
|
let mth_id = method_with_name_or_default(
|
||||||
bcx.ccx(), impl_did, mname);
|
bcx.ccx(), impl_did, mname);
|
||||||
|
|
||||||
@ -791,10 +792,11 @@ pub fn make_impl_vtable(ccx: @CrateContext,
|
|||||||
|| ~"make_impl_vtable: non-trait-type implemented");
|
|| ~"make_impl_vtable: non-trait-type implemented");
|
||||||
|
|
||||||
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
|
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
|
||||||
make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
|
make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| {
|
||||||
|
let im = ty::method(tcx, *method_def_id);
|
||||||
let fty = ty::subst_tps(tcx, substs, None,
|
let fty = ty::subst_tps(tcx, substs, None,
|
||||||
ty::mk_bare_fn(tcx, copy im.fty));
|
ty::mk_bare_fn(tcx, copy im.fty));
|
||||||
if (*im.tps).len() > 0u || ty::type_has_self(fty) {
|
if im.tps.len() > 0u || ty::type_has_self(fty) {
|
||||||
debug!("(making impl vtable) method has self or type params: %s",
|
debug!("(making impl vtable) method has self or type params: %s",
|
||||||
*tcx.sess.str_of(im.ident));
|
*tcx.sess.str_of(im.ident));
|
||||||
C_null(T_ptr(T_nil()))
|
C_null(T_ptr(T_nil()))
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
pub struct Reflector {
|
pub struct Reflector {
|
||||||
visitor_val: ValueRef,
|
visitor_val: ValueRef,
|
||||||
visitor_methods: @~[ty::method],
|
visitor_methods: @~[@ty::method],
|
||||||
final_bcx: block,
|
final_bcx: block,
|
||||||
tydesc_ty: TypeRef,
|
tydesc_ty: TypeRef,
|
||||||
bcx: block
|
bcx: block
|
||||||
|
@ -255,6 +255,15 @@ struct ctxt_ {
|
|||||||
// other items.
|
// other items.
|
||||||
node_type_substs: @mut HashMap<node_id, ~[t]>,
|
node_type_substs: @mut HashMap<node_id, ~[t]>,
|
||||||
|
|
||||||
|
// Maps from a method to the method "descriptor"
|
||||||
|
methods: @mut HashMap<def_id, @method>,
|
||||||
|
|
||||||
|
// Maps from a trait def-id to a list of the def-ids of its methods
|
||||||
|
trait_method_def_ids: @mut HashMap<def_id, @~[def_id]>,
|
||||||
|
|
||||||
|
// A cache for the trait_methods() routine
|
||||||
|
trait_methods_cache: @mut HashMap<def_id, @~[@method]>,
|
||||||
|
|
||||||
items: ast_map::map,
|
items: ast_map::map,
|
||||||
intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
|
intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
|
||||||
freevars: freevars::freevar_map,
|
freevars: freevars::freevar_map,
|
||||||
@ -266,7 +275,6 @@ struct ctxt_ {
|
|||||||
tc_cache: @mut HashMap<uint, TypeContents>,
|
tc_cache: @mut HashMap<uint, TypeContents>,
|
||||||
ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
|
ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
|
||||||
enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
|
enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
|
||||||
trait_method_cache: @mut HashMap<def_id, @~[method]>,
|
|
||||||
ty_param_bounds: @mut HashMap<ast::node_id, param_bounds>,
|
ty_param_bounds: @mut HashMap<ast::node_id, param_bounds>,
|
||||||
inferred_modes: @mut HashMap<ast::node_id, ast::mode>,
|
inferred_modes: @mut HashMap<ast::node_id, ast::mode>,
|
||||||
adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
|
adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
|
||||||
@ -831,7 +839,9 @@ pub fn mk_ctxt(s: session::Session,
|
|||||||
tc_cache: @mut HashMap::new(),
|
tc_cache: @mut HashMap::new(),
|
||||||
ast_ty_to_ty_cache: @mut HashMap::new(),
|
ast_ty_to_ty_cache: @mut HashMap::new(),
|
||||||
enum_var_cache: @mut HashMap::new(),
|
enum_var_cache: @mut HashMap::new(),
|
||||||
trait_method_cache: @mut HashMap::new(),
|
methods: @mut HashMap::new(),
|
||||||
|
trait_method_def_ids: @mut HashMap::new(),
|
||||||
|
trait_methods_cache: @mut HashMap::new(),
|
||||||
ty_param_bounds: @mut HashMap::new(),
|
ty_param_bounds: @mut HashMap::new(),
|
||||||
inferred_modes: @mut HashMap::new(),
|
inferred_modes: @mut HashMap::new(),
|
||||||
adjustments: @mut HashMap::new(),
|
adjustments: @mut HashMap::new(),
|
||||||
@ -3028,7 +3038,7 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
|
|||||||
let trt_bounds =
|
let trt_bounds =
|
||||||
ty::lookup_item_type(tcx, trt_id).bounds;
|
ty::lookup_item_type(tcx, trt_id).bounds;
|
||||||
@(vec::append(/*bad*/copy *trt_bounds,
|
@(vec::append(/*bad*/copy *trt_bounds,
|
||||||
*ty::trait_methods(tcx, trt_id)[n_mth].tps))
|
*ty::trait_method(tcx, trt_id, n_mth).tps))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3213,10 +3223,8 @@ pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
|
|||||||
fields.map(|f| tcx.sess.str_of(f.ident))));
|
fields.map(|f| tcx.sess.str_of(f.ident))));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn method_idx(id: ast::ident, meths: &[method]) -> Option<uint> {
|
pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option<uint> {
|
||||||
let mut i = 0u;
|
vec::position(meths, |m| m.ident == id)
|
||||||
for meths.each |m| { if m.ident == id { return Some(i); } i += 1u; }
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vector containing the indices of all type parameters that appear
|
/// Returns a vector containing the indices of all type parameters that appear
|
||||||
@ -3537,10 +3545,6 @@ pub fn def_has_ty_params(def: ast::def) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
|
|
||||||
cx.trait_method_cache.insert(ast_util::local_def(id), ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
|
pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
|
||||||
if is_local(id) {
|
if is_local(id) {
|
||||||
match cx.items.find(&id.node) {
|
match cx.items.find(&id.node) {
|
||||||
@ -3594,23 +3598,64 @@ pub fn trait_supertraits(cx: ctxt,
|
|||||||
return @result;
|
return @result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
|
fn lookup_locally_or_in_crate_store<V:Copy>(
|
||||||
match cx.trait_method_cache.find(&id) {
|
descr: &str,
|
||||||
// Local traits are supposed to have been added explicitly.
|
def_id: ast::def_id,
|
||||||
Some(&ms) => ms,
|
map: &mut HashMap<ast::def_id, V>,
|
||||||
_ => {
|
load_external: &fn() -> V) -> V
|
||||||
// If the lookup in trait_method_cache fails, assume that the trait
|
{
|
||||||
// method we're trying to look up is in a different crate, and look
|
/*!
|
||||||
// for it there.
|
*
|
||||||
assert!(id.crate != ast::local_crate);
|
* Helper for looking things up in the various maps
|
||||||
let result = csearch::get_trait_methods(cx, id);
|
* that are populated during typeck::collect (e.g.,
|
||||||
|
* `cx.methods`, `cx.tcache`, etc). All of these share
|
||||||
|
* the pattern that if the id is local, it should have
|
||||||
|
* been loaded into the map by the `typeck::collect` phase.
|
||||||
|
* If the def-id is external, then we have to go consult
|
||||||
|
* the crate loading code (and cache the result for the future).
|
||||||
|
*/
|
||||||
|
|
||||||
// Store the trait method in the local trait_method_cache so that
|
match map.find(&def_id) {
|
||||||
// future lookups succeed.
|
Some(&v) => { return v; }
|
||||||
cx.trait_method_cache.insert(id, result);
|
None => { }
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if def_id.crate == ast::local_crate {
|
||||||
|
fail!(fmt!("No def'n found for %? in tcx.%s",
|
||||||
|
def_id, descr));
|
||||||
|
}
|
||||||
|
let v = load_external();
|
||||||
|
map.insert(def_id, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @method {
|
||||||
|
let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx];
|
||||||
|
ty::method(cx, method_def_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] {
|
||||||
|
match cx.trait_methods_cache.find(&trait_did) {
|
||||||
|
Some(&methods) => methods,
|
||||||
|
None => {
|
||||||
|
let def_ids = ty::trait_method_def_ids(cx, trait_did);
|
||||||
|
let methods = @def_ids.map(|d| ty::method(cx, *d));
|
||||||
|
cx.trait_methods_cache.insert(trait_did, methods);
|
||||||
|
methods
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn method(cx: ctxt, id: ast::def_id) -> @method {
|
||||||
|
lookup_locally_or_in_crate_store(
|
||||||
|
"methods", id, cx.methods,
|
||||||
|
|| @csearch::get_method(cx, id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
|
||||||
|
lookup_locally_or_in_crate_store(
|
||||||
|
"methods", id, cx.trait_method_def_ids,
|
||||||
|
|| @csearch::get_trait_method_def_ids(cx.cstore, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3916,19 +3961,9 @@ pub fn enum_variant_with_id(cx: ctxt,
|
|||||||
pub fn lookup_item_type(cx: ctxt,
|
pub fn lookup_item_type(cx: ctxt,
|
||||||
did: ast::def_id)
|
did: ast::def_id)
|
||||||
-> ty_param_bounds_and_ty {
|
-> ty_param_bounds_and_ty {
|
||||||
match cx.tcache.find(&did) {
|
lookup_locally_or_in_crate_store(
|
||||||
Some(&tpt) => {
|
"tcache", did, cx.tcache,
|
||||||
// The item is in this crate. The caller should have added it to the
|
|| csearch::get_type(cx, did))
|
||||||
// type cache already
|
|
||||||
return tpt;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
assert!(did.crate != ast::local_crate);
|
|
||||||
let tyt = csearch::get_type(cx, did);
|
|
||||||
cx.tcache.insert(did, tyt);
|
|
||||||
return tyt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look up a field ID, whether or not it's local
|
// Look up a field ID, whether or not it's local
|
||||||
|
@ -243,7 +243,7 @@ fn mk_pointer<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||||
return ty::mk_estr(tcx, vst);
|
return ty::mk_estr(tcx, vst);
|
||||||
}
|
}
|
||||||
Some(&ast::def_ty(type_def_id)) => {
|
Some(&ast::def_trait(type_def_id)) => {
|
||||||
let result = ast_path_to_substs_and_ty(
|
let result = ast_path_to_substs_and_ty(
|
||||||
self, rscope,
|
self, rscope,
|
||||||
type_def_id, path);
|
type_def_id, path);
|
||||||
@ -271,7 +271,11 @@ fn mk_pointer<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||||||
trait_store);
|
trait_store);
|
||||||
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {
|
||||||
|
tcx.sess.span_bug(
|
||||||
|
a_seq_ty.ty.span,
|
||||||
|
fmt!("def_trait but not ty_trait"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -372,7 +376,7 @@ fn check_path_args(tcx: ty::ctxt,
|
|||||||
Some(&d) => d
|
Some(&d) => d
|
||||||
};
|
};
|
||||||
match a_def {
|
match a_def {
|
||||||
ast::def_ty(did) | ast::def_struct(did) => {
|
ast::def_trait(did) | ast::def_ty(did) | ast::def_struct(did) => {
|
||||||
ast_path_to_ty(self, rscope, did, path).ty
|
ast_path_to_ty(self, rscope, did, path).ty
|
||||||
}
|
}
|
||||||
ast::def_prim_ty(nty) => {
|
ast::def_prim_ty(nty) => {
|
||||||
|
@ -2126,11 +2126,11 @@ fn check_loop_body(fcx: @mut FnCtxt,
|
|||||||
ast::expr_vstore(ev, vst) => {
|
ast::expr_vstore(ev, vst) => {
|
||||||
let typ = match ev.node {
|
let typ = match ev.node {
|
||||||
ast::expr_lit(@codemap::spanned { node: ast::lit_str(s), _ }) => {
|
ast::expr_lit(@codemap::spanned { node: ast::lit_str(s), _ }) => {
|
||||||
let tt = ast_expr_vstore_to_vstore(fcx, ev, s.len(), vst);
|
let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
|
||||||
ty::mk_estr(tcx, tt)
|
ty::mk_estr(tcx, tt)
|
||||||
}
|
}
|
||||||
ast::expr_vec(ref args, mutbl) => {
|
ast::expr_vec(ref args, mutbl) => {
|
||||||
let tt = ast_expr_vstore_to_vstore(fcx, ev, args.len(), vst);
|
let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
|
||||||
let mutability;
|
let mutability;
|
||||||
let mut any_error = false;
|
let mut any_error = false;
|
||||||
let mut any_bot = false;
|
let mut any_bot = false;
|
||||||
@ -2164,7 +2164,7 @@ fn check_loop_body(fcx: @mut FnCtxt,
|
|||||||
ast::expr_repeat(element, count_expr, mutbl) => {
|
ast::expr_repeat(element, count_expr, mutbl) => {
|
||||||
let count = ty::eval_repeat_count(tcx, count_expr);
|
let count = ty::eval_repeat_count(tcx, count_expr);
|
||||||
check_expr_with_hint(fcx, count_expr, ty::mk_uint(tcx));
|
check_expr_with_hint(fcx, count_expr, ty::mk_uint(tcx));
|
||||||
let tt = ast_expr_vstore_to_vstore(fcx, ev, count, vst);
|
let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
|
||||||
let mutability = match vst {
|
let mutability = match vst {
|
||||||
ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => {
|
ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => {
|
||||||
ast::m_mutbl
|
ast::m_mutbl
|
||||||
@ -3173,7 +3173,10 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
|
|||||||
ast::def_upvar(_, inner, _, _) => {
|
ast::def_upvar(_, inner, _, _) => {
|
||||||
return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
|
return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
|
||||||
}
|
}
|
||||||
ast::def_ty(_) | ast::def_prim_ty(_) | ast::def_ty_param(*)=> {
|
ast::def_trait(_) |
|
||||||
|
ast::def_ty(_) |
|
||||||
|
ast::def_prim_ty(_) |
|
||||||
|
ast::def_ty_param(*)=> {
|
||||||
fcx.ccx.tcx.sess.span_bug(sp, ~"expected value but found type");
|
fcx.ccx.tcx.sess.span_bug(sp, ~"expected value but found type");
|
||||||
}
|
}
|
||||||
ast::def_mod(*) | ast::def_foreign_mod(*) => {
|
ast::def_mod(*) | ast::def_foreign_mod(*) => {
|
||||||
@ -3211,6 +3214,10 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
|
|||||||
let ty_param_count = vec::len(*tpt.bounds);
|
let ty_param_count = vec::len(*tpt.bounds);
|
||||||
let ty_substs_len = vec::len(pth.types);
|
let ty_substs_len = vec::len(pth.types);
|
||||||
|
|
||||||
|
debug!("ty_param_count=%? ty_substs_len=%?",
|
||||||
|
ty_param_count,
|
||||||
|
ty_substs_len);
|
||||||
|
|
||||||
// determine the region bound, using the value given by the user
|
// determine the region bound, using the value given by the user
|
||||||
// (if any) and otherwise using a fresh region variable
|
// (if any) and otherwise using a fresh region variable
|
||||||
let self_r = match pth.rp {
|
let self_r = match pth.rp {
|
||||||
@ -3306,7 +3313,6 @@ pub fn type_is_c_like_enum(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
|
|||||||
|
|
||||||
pub fn ast_expr_vstore_to_vstore(fcx: @mut FnCtxt,
|
pub fn ast_expr_vstore_to_vstore(fcx: @mut FnCtxt,
|
||||||
e: @ast::expr,
|
e: @ast::expr,
|
||||||
_n: uint,
|
|
||||||
v: ast::expr_vstore)
|
v: ast::expr_vstore)
|
||||||
-> ty::vstore {
|
-> ty::vstore {
|
||||||
match v {
|
match v {
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
use middle::typeck::infer::InferCtxt;
|
use middle::typeck::infer::InferCtxt;
|
||||||
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
|
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
|
||||||
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
|
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
|
||||||
use syntax::ast::{crate, def_id, def_mod, def_ty};
|
use syntax::ast::{crate, def_id, def_mod, def_ty, def_trait};
|
||||||
use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref};
|
use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast_map::node_item;
|
use syntax::ast_map::node_item;
|
||||||
@ -507,7 +507,7 @@ fn each_provided_trait_method(&self,
|
|||||||
provided_method_idents.insert(*ident);
|
provided_method_idents.insert(*ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ty::trait_methods(tcx, trait_did).each |method| {
|
for ty::trait_methods(tcx, trait_did).each |&method| {
|
||||||
if provided_method_idents.contains(&method.ident) {
|
if provided_method_idents.contains(&method.ident) {
|
||||||
if !f(method) {
|
if !f(method) {
|
||||||
break;
|
break;
|
||||||
@ -947,7 +947,7 @@ fn add_external_crates(&self) {
|
|||||||
crate_store,
|
crate_store,
|
||||||
def_id);
|
def_id);
|
||||||
}
|
}
|
||||||
dl_def(def_ty(def_id)) => {
|
dl_def(def_trait(def_id)) => {
|
||||||
let tcx = self.crate_context.tcx;
|
let tcx = self.crate_context.tcx;
|
||||||
let polytype = csearch::get_type(tcx, def_id);
|
let polytype = csearch::get_type(tcx, def_id);
|
||||||
match ty::get(polytype.ty).sty {
|
match ty::get(polytype.ty).sty {
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast_map;
|
use syntax::ast_map;
|
||||||
use syntax::ast_util::{local_def, split_trait_methods};
|
use syntax::ast_util::{local_def, split_trait_methods};
|
||||||
use syntax::ast_util::{trait_method_to_ty_method};
|
|
||||||
use syntax::ast_util;
|
use syntax::ast_util;
|
||||||
use syntax::codemap::span;
|
use syntax::codemap::span;
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
@ -221,19 +220,61 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
||||||
id: ast::node_id,
|
trait_id: ast::node_id,
|
||||||
trait_ty: ty::t) {
|
trait_ty: ty::t)
|
||||||
fn store_methods<T>(ccx: &CrateCtxt,
|
{
|
||||||
id: ast::node_id,
|
let tcx = ccx.tcx;
|
||||||
stuff: &[T],
|
let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x);
|
||||||
f: &fn(v: &T) -> ty::method) {
|
match *tcx.items.get(&trait_id) {
|
||||||
ty::store_trait_methods(ccx.tcx, id, @stuff.map(f));
|
ast_map::node_item(@ast::item {
|
||||||
|
node: ast::item_trait(ref generics, _, ref ms),
|
||||||
|
_
|
||||||
|
}, _) => {
|
||||||
|
let trait_bounds = ty_param_bounds(ccx, generics);
|
||||||
|
|
||||||
|
// For each method, construct a suitable ty::method and
|
||||||
|
// store it into the `tcx.methods` table:
|
||||||
|
for ms.each |m| {
|
||||||
|
let ty_method = @match m {
|
||||||
|
&ast::required(ref m) => {
|
||||||
|
ty_method_of_trait_method(ccx, region_paramd, generics,
|
||||||
|
&m.id, &m.ident, &m.self_ty,
|
||||||
|
&m.generics, &m.purity, &m.decl)
|
||||||
|
}
|
||||||
|
|
||||||
|
&ast::provided(ref m) => {
|
||||||
|
ty_method_of_trait_method(ccx, region_paramd, generics,
|
||||||
|
&m.id, &m.ident, &m.self_ty,
|
||||||
|
&m.generics, &m.purity, &m.decl)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ty_method.self_ty == ast::sty_static {
|
||||||
|
make_static_method_ty(ccx, region_paramd,
|
||||||
|
ty_method, trait_ty,
|
||||||
|
trait_bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
tcx.methods.insert(ty_method.def_id, ty_method);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an entry mapping
|
||||||
|
let method_def_ids = @ms.map(|m| {
|
||||||
|
match m {
|
||||||
|
&ast::required(ref ty_method) => local_def(ty_method.id),
|
||||||
|
&ast::provided(ref method) => local_def(method.id)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let trait_def_id = local_def(trait_id);
|
||||||
|
tcx.trait_method_def_ids.insert(trait_def_id, method_def_ids);
|
||||||
|
}
|
||||||
|
_ => { /* Ignore things that aren't traits */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_static_method_ty(ccx: &CrateCtxt,
|
fn make_static_method_ty(ccx: &CrateCtxt,
|
||||||
am: &ast::ty_method,
|
|
||||||
rp: Option<ty::region_variance>,
|
rp: Option<ty::region_variance>,
|
||||||
m: ty::method,
|
m: &ty::method,
|
||||||
// Take this as an argument b/c we may check
|
// Take this as an argument b/c we may check
|
||||||
// the impl before the trait.
|
// the impl before the trait.
|
||||||
trait_ty: ty::t,
|
trait_ty: ty::t,
|
||||||
@ -267,7 +308,7 @@ fn make_static_method_ty(ccx: &CrateCtxt,
|
|||||||
ty::mk_bare_fn(ccx.tcx, copy m.fty));
|
ty::mk_bare_fn(ccx.tcx, copy m.fty));
|
||||||
let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
|
let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
|
||||||
+ *m.tps);
|
+ *m.tps);
|
||||||
ccx.tcx.tcache.insert(local_def(am.id),
|
ccx.tcx.tcache.insert(m.def_id,
|
||||||
ty_param_bounds_and_ty {
|
ty_param_bounds_and_ty {
|
||||||
bounds: bounds,
|
bounds: bounds,
|
||||||
region_param: rp,
|
region_param: rp,
|
||||||
@ -275,40 +316,31 @@ fn make_static_method_ty(ccx: &CrateCtxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let tcx = ccx.tcx;
|
fn ty_method_of_trait_method(self: &CrateCtxt,
|
||||||
let region_paramd = tcx.region_paramd_items.find(&id).map_consume(|x| *x);
|
trait_rp: Option<ty::region_variance>,
|
||||||
match *tcx.items.get(&id) {
|
trait_generics: &ast::Generics,
|
||||||
ast_map::node_item(@ast::item {
|
m_id: &ast::node_id,
|
||||||
node: ast::item_trait(ref generics, _, ref ms),
|
m_ident: &ast::ident,
|
||||||
_
|
m_self_ty: &ast::self_ty,
|
||||||
}, _) => {
|
m_generics: &ast::Generics,
|
||||||
store_methods::<ast::trait_method>(ccx, id, *ms, |m| {
|
m_purity: &ast::purity,
|
||||||
let def_id;
|
m_decl: &ast::fn_decl) -> ty::method
|
||||||
match *m {
|
{
|
||||||
ast::required(ref ty_method) => {
|
let rscope = MethodRscope::new(m_self_ty.node, trait_rp, trait_generics);
|
||||||
def_id = local_def((*ty_method).id)
|
ty::method {
|
||||||
}
|
ident: *m_ident,
|
||||||
ast::provided(method) => def_id = local_def(method.id)
|
tps: ty_param_bounds(self, m_generics),
|
||||||
}
|
fty: astconv::ty_of_bare_fn(self,
|
||||||
|
&rscope,
|
||||||
let trait_bounds = ty_param_bounds(ccx, generics);
|
*m_purity,
|
||||||
let ty_m = trait_method_to_ty_method(m);
|
AbiSet::Rust(),
|
||||||
let method_ty = ty_of_ty_method(
|
&m_generics.lifetimes,
|
||||||
ccx,
|
m_decl),
|
||||||
&ty_m,
|
// assume public, because this is only invoked on trait methods
|
||||||
region_paramd,
|
self_ty: m_self_ty.node,
|
||||||
def_id,
|
vis: ast::public,
|
||||||
generics
|
def_id: local_def(*m_id)
|
||||||
);
|
}
|
||||||
if ty_m.self_ty.node == ast::sty_static {
|
|
||||||
make_static_method_ty(ccx, &ty_m, region_paramd,
|
|
||||||
method_ty, trait_ty,
|
|
||||||
trait_bounds);
|
|
||||||
}
|
|
||||||
method_ty
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => { /* Ignore things that aren't traits */ }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,8 +533,8 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
|
|||||||
rp: Option<ty::region_variance>,
|
rp: Option<ty::region_variance>,
|
||||||
selfty: ty::t,
|
selfty: ty::t,
|
||||||
a_trait_ty: @ast::trait_ref,
|
a_trait_ty: @ast::trait_ref,
|
||||||
impl_ms: &[ConvertedMethod]) {
|
impl_ms: &[ConvertedMethod])
|
||||||
|
{
|
||||||
let tcx = ccx.tcx;
|
let tcx = ccx.tcx;
|
||||||
let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp, generics);
|
let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp, generics);
|
||||||
|
|
||||||
@ -530,7 +562,7 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
|
|||||||
let trait_ms = ty::trait_methods(tcx, did);
|
let trait_ms = ty::trait_methods(tcx, did);
|
||||||
for impl_ms.each |impl_m| {
|
for impl_ms.each |impl_m| {
|
||||||
match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) {
|
match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) {
|
||||||
Some(ref trait_m) => {
|
Some(trait_m) => {
|
||||||
let num_impl_tps = generics.ty_params.len();
|
let num_impl_tps = generics.ty_params.len();
|
||||||
compare_impl_method(
|
compare_impl_method(
|
||||||
ccx.tcx, num_impl_tps, impl_m, trait_m,
|
ccx.tcx, num_impl_tps, impl_m, trait_m,
|
||||||
@ -786,29 +818,6 @@ pub fn ty_of_method(ccx: &CrateCtxt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty_of_ty_method(self: &CrateCtxt,
|
|
||||||
m: &ast::ty_method,
|
|
||||||
rp: Option<ty::region_variance>,
|
|
||||||
id: ast::def_id,
|
|
||||||
generics: &ast::Generics)
|
|
||||||
-> ty::method {
|
|
||||||
let rscope = MethodRscope::new(m.self_ty.node, rp, generics);
|
|
||||||
ty::method {
|
|
||||||
ident: m.ident,
|
|
||||||
tps: ty_param_bounds(self, &m.generics),
|
|
||||||
fty: astconv::ty_of_bare_fn(self,
|
|
||||||
&rscope,
|
|
||||||
m.purity,
|
|
||||||
AbiSet::Rust(),
|
|
||||||
&m.generics.lifetimes,
|
|
||||||
&m.decl),
|
|
||||||
// assume public, because this is only invoked on trait methods
|
|
||||||
self_ty: m.self_ty.node,
|
|
||||||
vis: ast::public,
|
|
||||||
def_id: id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Instantiates the path for the given trait reference, assuming that
|
Instantiates the path for the given trait reference, assuming that
|
||||||
it's bound to a valid trait type. Returns the def_id for the defining
|
it's bound to a valid trait type. Returns the def_id for the defining
|
||||||
@ -828,7 +837,7 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
|
|||||||
let rscope = type_rscope(rp);
|
let rscope = type_rscope(rp);
|
||||||
|
|
||||||
match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) {
|
match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) {
|
||||||
ast::def_ty(t_id) => {
|
ast::def_trait(t_id) => {
|
||||||
let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path);
|
let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path);
|
||||||
|
|
||||||
write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt);
|
write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt);
|
||||||
|
@ -443,7 +443,7 @@ fn field_to_str(cx: ctxt, f: field) -> ~str {
|
|||||||
str::from_bytes(~[('a' as u8) + (id as u8)]))
|
str::from_bytes(~[('a' as u8) + (id as u8)]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty_self(*) => ~"self",
|
ty_self(*) => ~"Self",
|
||||||
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
|
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
|
||||||
let path = ty::item_path(cx, did);
|
let path = ty::item_path(cx, did);
|
||||||
let base = ast_map::path_to_str(path, cx.sess.intr());
|
let base = ast_map::path_to_str(path, cx.sess.intr());
|
||||||
|
@ -194,6 +194,7 @@ pub enum def {
|
|||||||
def_local(node_id, bool /* is_mutbl */),
|
def_local(node_id, bool /* is_mutbl */),
|
||||||
def_variant(def_id /* enum */, def_id /* variant */),
|
def_variant(def_id /* enum */, def_id /* variant */),
|
||||||
def_ty(def_id),
|
def_ty(def_id),
|
||||||
|
def_trait(def_id),
|
||||||
def_prim_ty(prim_ty),
|
def_prim_ty(prim_ty),
|
||||||
def_ty_param(def_id, uint),
|
def_ty_param(def_id, uint),
|
||||||
def_binding(node_id, binding_mode),
|
def_binding(node_id, binding_mode),
|
||||||
|
@ -61,7 +61,7 @@ pub fn def_id_of_def(d: def) -> def_id {
|
|||||||
def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) |
|
def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) |
|
||||||
def_foreign_mod(id) | def_const(id) |
|
def_foreign_mod(id) | def_const(id) |
|
||||||
def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
|
def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
|
||||||
def_use(id) | def_struct(id) => {
|
def_use(id) | def_struct(id) | def_trait(id) => {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
def_arg(id, _, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)
|
def_arg(id, _, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// error-pattern:expected function or foreign function but found `*u8`
|
// error-pattern:expected function but found `*u8`
|
||||||
extern fn f() {
|
extern fn f() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
trait A {
|
trait A {
|
||||||
fn a(&self) {
|
fn a(&self) {
|
||||||
|| self.b() //~ ERROR type `&'self self` does not implement any method in scope named `b`
|
|| self.b() //~ ERROR type `&'self Self` does not implement any method in scope named `b`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user