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:
Niko Matsakis 2013-03-27 10:26:57 -04:00
parent d94830830f
commit 007abe9352
24 changed files with 412 additions and 321 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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> {

View File

@ -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(&param.id)); @params.map_to_vec(|param| *ecx.tcx.ty_param_bounds.get(&param.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")
} }

View File

@ -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);

View File

@ -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);

View File

@ -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),

View File

@ -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(*) => {

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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(*) |

View File

@ -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()))

View File

@ -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

View File

@ -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

View File

@ -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) => {

View File

@ -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 {

View File

@ -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 {

View File

@ -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);

View File

@ -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());

View File

@ -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),

View File

@ -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)

View File

@ -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() {
} }

View File

@ -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() {}