diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 920631a55b4e..d3b06009d727 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -102,6 +102,7 @@ pub static tag_item_dtor: uint = 0x49u; pub static tag_item_trait_method_self_ty: uint = 0x4b; pub static tag_item_trait_method_self_ty_region: uint = 0x4c; + // Reexports are found within module tags. Each reexport contains def_ids // and names. pub static tag_items_data_item_reexport: uint = 0x4d; @@ -159,6 +160,9 @@ pub static tag_items_data_item_visibility: uint = 0x78; pub static tag_link_args: uint = 0x79; 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 { name: @str, vers: @str, diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 16b896f11d6a..8e7ecdec638b 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -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, - def: ast::def_id) - -> @~[ty::method] { - let cstore = tcx.cstore; +pub fn get_method(tcx: ty::ctxt, + def: ast::def_id) -> ty::method +{ + 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); - 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, @@ -133,13 +145,6 @@ pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] { 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) -> Option { let cdata = cstore::get_crate_data(cstore, def.crate); diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index dcea22b09d6d..800df628bc23 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -19,7 +19,8 @@ use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo}; use metadata::csearch; use metadata::cstore; 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 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)) } +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, tcx: ty::ctxt, cdata: cmd) -> ty::t { 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 } -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] { 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, |_, did| translate_def_id(cdata, did)); 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); 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), 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, cdata); 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 { @~[] }; let rp = item_ty_region_param(item); ty::ty_param_bounds_and_ty { @@ -690,36 +699,46 @@ pub fn get_impls_for_mod(intr: @ident_interner, @result } -/* Works for both classes and traits */ -pub fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, - tcx: ty::ctxt) -> @~[ty::method] { +pub fn get_method_name_and_self_ty( + intr: @ident_interner, + 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 item = lookup_item(id, data); let mut result = ~[]; for reader::tagged_docs(item, tag_item_trait_method) |mth| { - let bounds = item_ty_param_bounds(mth, tcx, 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 - }); + result.push(item_def_id(mth, cdata)); } - debug!("get_trait_methods: }"); - @result + result } 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 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 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; } -// 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, cdata: cmd, node_id: ast::node_id) -> Option { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 6000e559554f..61501d830833 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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) } -fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext, - params: @~[ty::param_bounds]) { +fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, + ecx: @EncodeContext, + params: @~[ty::param_bounds], + tag: uint) { let ty_str_ctxt = @tyencode::ctxt { diag: ecx.diag, 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), abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; 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); ebml_w.end_tag(); } @@ -190,7 +192,8 @@ fn encode_type_param_bounds(ebml_w: writer::Encoder, params: &OptVec) { let ty_param_bounds = @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(); } +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) { ebml_w.start_tag(tag_items_data_item_symbol); match ecx.item_symbols.find(&id) { @@ -868,8 +888,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, } } item_trait(ref generics, ref traits, ref ms) => { - let mut provided_methods = ~[]; - add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); @@ -879,97 +897,90 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); - let mut i = 0u; - for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| { - match (*ms)[i] { - required(ref ty_m) => { - 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; + for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| { + ebml_w.start_tag(tag_item_trait_method); + encode_def_id(ebml_w, method_def_id); + ebml_w.end_tag(); } encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); 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(); - // Now, output all of the static methods as items. Note that for the - // method info, we output static methods with type signatures as - // written. Here, we output the *real* type signatures. I feel like - // maybe we should only ever handle the real type signatures. - for ms.each |m| { - let ty_m = ast_util::trait_method_to_ty_method(m); - if ty_m.self_ty.node != ast::sty_static { loop; } + // Now output the method info for each method. + // + // Note: for the moment, the data structures here are *slightly* + // different from those expected by `encode_info_for_method()`, + // but I do plan to refactor this later in this patch to avoid the + // duplication. + 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); - 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 - // real visibility in the AST. - encode_visibility(ebml_w, item.vis); + encode_def_id(ebml_w, method_def_id); + encode_parent_item(ebml_w, local_def(item.id)); + 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(); } - - // 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") } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 111bc307ed30..2982ed268770 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -119,6 +119,12 @@ pub fn parse_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, 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, conv: conv_did) -> ty::arg { let st = parse_state_from_data(data, crate_num, pos, tcx); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 251ba9b35cbd..419219d411d8 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -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_abi_set(w, ft.abis); enc_fn_sig(w, cx, &ft.sig); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index b6b6730620e9..6fc74c9a7130 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -417,6 +417,7 @@ impl tr for ast::def { ast::def_variant(e_did, v_did) => { 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_prim_ty(p) => ast::def_prim_ty(p), ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v), diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index b7ec6208d560..6473cb8e8e00 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -462,7 +462,7 @@ pub impl mem_categorization_ctxt { ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) | ast::def_foreign_mod(_) | ast::def_const(_) | 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_typaram_binder(*) | ast::def_region(_) | ast::def_label(_) | ast::def_self_ty(*) => { diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 7740485e82c0..ed7ca441b984 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -211,7 +211,7 @@ use core::prelude::*; use middle::pat_util::{pat_bindings}; use middle::freevars; use middle::ty; -use middle::typeck::method_map; +use middle::typeck::{method_map, method_map_entry}; use util::ppaux; use util::common::indenter; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 75eb8ef1a858..1c60c37ed12a 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -690,7 +690,9 @@ pub fn determine_rp_in_ty(ty: @ast::Ty, match ty.node { ast::ty_path(path, 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 cx.region_is_relevant(path.rp) { cx.add_dep(did.node); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 08542301e238..7232e99bf220 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -12,7 +12,8 @@ use core::prelude::*; use driver::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_type_name_if_impl; use metadata::cstore::find_extern_mod_stmt_cnum; @@ -31,7 +32,7 @@ use syntax::ast::{crate, decl_item, def, def_arg, def_binding}; 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_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::{expr_binary, expr_break, expr_field}; use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path}; @@ -1341,7 +1342,7 @@ pub impl Resolver { let def_id = local_def(item.id); 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); } @@ -1611,36 +1612,40 @@ pub impl Resolver { crate) building value %s", final_ident); child_name_bindings.define_value(Public, def, dummy_sp()); } - def_ty(def_id) => { - debug!("(building reduced graph for external \ - crate) building type %s", final_ident); + def_trait(def_id) => { + debug!("(building reduced graph for external \ + crate) building type %s", final_ident); - // If this is a trait, add all the method names - // to the trait info. + // If this is a trait, add all the method names + // to the trait info. - match get_method_names_if_trait(self.session.cstore, def_id) { - None => { - // Nothing to do. + let method_def_ids = get_trait_method_def_ids(self.session.cstore, + def_id); + 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) => { - 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)); + self.trait_info.insert(def_id, interned_method_names); - // Add it to the trait info if not static. - if self_ty != sty_static { - interned_method_names.insert(method_name); - } - } - self.trait_info.insert(def_id, interned_method_names); - } - } + child_name_bindings.define_type(Public, def, dummy_sp()); + } + def_ty(_) => { + debug!("(building reduced graph for external \ + crate) building type %s", final_ident); - child_name_bindings.define_type(Public, def, dummy_sp()); + child_name_bindings.define_type(Public, def, dummy_sp()); } def_struct(def_id) => { debug!("(building reduced graph for external \ @@ -4952,7 +4957,7 @@ pub impl Resolver { match child_name_bindings.def_for_namespace(TypeNS) { Some(def) => { match def { - def_ty(trait_def_id) => { + def_trait(trait_def_id) => { self.add_trait_info_if_containing_method( &mut found_traits, trait_def_id, name); } @@ -4979,7 +4984,7 @@ pub impl Resolver { match target.bindings.def_for_namespace(TypeNS) { Some(def) => { match def { - def_ty(trait_def_id) => { + def_trait(trait_def_id) => { let added = self. add_trait_info_if_containing_method( &mut found_traits, diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index ec67c68f93cd..b8b0bddcf051 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -148,7 +148,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee { ast::def_self(*) => { 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_use(*) | ast::def_typaram_binder(*) | ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) | diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index ed9000e7418a..accdb6557501 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -174,6 +174,7 @@ pub fn trans_method_callee(bcx: block, mentry: typeck::method_map_entry) -> Callee { let _icx = bcx.insn_ctxt("impl::trans_method_callee"); + let tcx = bcx.tcx(); debug!("trans_method_callee(callee_id=%?, self=%s, 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. let method_name = - ty::trait_methods(bcx.tcx(), trait_id)[method_index].ident; - let method_id = method_with_name(bcx.ccx(), impl_def_id, - method_name); + ty::trait_method(tcx, trait_id, method_index).ident; + let method_id = + method_with_name(bcx.ccx(), impl_def_id, method_name); origin = typeck::method_static(method_id); } typeck::method_super(trait_id, method_index) => { // is the self type for this method call let self_ty = node_id_type(bcx, self.id); - let tcx = bcx.tcx(); // is the ID of the implementation of // trait for type let impl_id = ty::get_impl_id(tcx, trait_id, self_ty); // 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 // 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 \ index is out of bounds"); } // 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 // ID from its name origin = typeck::method_static(method_with_name(bcx.ccx(), - impl_id, - method_name)); + impl_id, + method_name)); } typeck::method_static(*) | typeck::method_param(*) | typeck::method_trait(*) => {} @@ -448,7 +449,7 @@ pub fn trans_monomorphized_callee(bcx: block, return match vtbl { typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { 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( bcx.ccx(), impl_did, mname); @@ -791,10 +792,11 @@ pub fn make_impl_vtable(ccx: @CrateContext, || ~"make_impl_vtable: non-trait-type implemented"); 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, 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", *tcx.sess.str_of(im.ident)); C_null(T_ptr(T_nil())) diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index a9869f15875c..224981d6e759 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -31,7 +31,7 @@ use syntax::ast; pub struct Reflector { visitor_val: ValueRef, - visitor_methods: @~[ty::method], + visitor_methods: @~[@ty::method], final_bcx: block, tydesc_ty: TypeRef, bcx: block diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 19ffb4edc844..fcdd5a650af8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -255,6 +255,15 @@ struct ctxt_ { // other items. node_type_substs: @mut HashMap, + // Maps from a method to the method "descriptor" + methods: @mut HashMap, + + // Maps from a trait def-id to a list of the def-ids of its methods + trait_method_def_ids: @mut HashMap, + + // A cache for the trait_methods() routine + trait_methods_cache: @mut HashMap, + items: ast_map::map, intrinsic_defs: @mut HashMap, freevars: freevars::freevar_map, @@ -266,7 +275,6 @@ struct ctxt_ { tc_cache: @mut HashMap, ast_ty_to_ty_cache: @mut HashMap, enum_var_cache: @mut HashMap, - trait_method_cache: @mut HashMap, ty_param_bounds: @mut HashMap, inferred_modes: @mut HashMap, adjustments: @mut HashMap, @@ -831,7 +839,9 @@ pub fn mk_ctxt(s: session::Session, tc_cache: @mut HashMap::new(), ast_ty_to_ty_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(), inferred_modes: @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 = ty::lookup_item_type(tcx, trt_id).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)))); } -pub fn method_idx(id: ast::ident, meths: &[method]) -> Option { - let mut i = 0u; - for meths.each |m| { if m.ident == id { return Some(i); } i += 1u; } - return None; +pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option { + vec::position(meths, |m| m.ident == id) } /// 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] { if is_local(id) { match cx.items.find(&id.node) { @@ -3594,23 +3598,64 @@ pub fn trait_supertraits(cx: ctxt, return @result; } -pub fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] { - match cx.trait_method_cache.find(&id) { - // Local traits are supposed to have been added explicitly. - Some(&ms) => ms, - _ => { - // 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); - let result = csearch::get_trait_methods(cx, id); +fn lookup_locally_or_in_crate_store( + descr: &str, + def_id: ast::def_id, + map: &mut HashMap, + load_external: &fn() -> V) -> V +{ + /*! + * + * Helper for looking things up in the various maps + * 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 - // future lookups succeed. - cx.trait_method_cache.insert(id, result); - result - } + match map.find(&def_id) { + Some(&v) => { return v; } + None => { } } + + 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, did: ast::def_id) -> ty_param_bounds_and_ty { - match cx.tcache.find(&did) { - Some(&tpt) => { - // The item is in this crate. The caller should have added it to the - // 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; - } - } + lookup_locally_or_in_crate_store( + "tcache", did, cx.tcache, + || csearch::get_type(cx, did)) } // Look up a field ID, whether or not it's local diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 4b4cb8572529..c54e76b9c057 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -243,7 +243,7 @@ pub fn ast_ty_to_ty( check_path_args(tcx, path, NO_TPS | NO_REGIONS); 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( self, rscope, type_def_id, path); @@ -271,7 +271,11 @@ pub fn ast_ty_to_ty( trait_store); } - _ => {} + _ => { + tcx.sess.span_bug( + a_seq_ty.ty.span, + fmt!("def_trait but not ty_trait")); + } } } _ => {} @@ -372,7 +376,7 @@ pub fn ast_ty_to_ty( Some(&d) => d }; 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::def_prim_ty(nty) => { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 320094957721..c8b274e45691 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2126,11 +2126,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ast::expr_vstore(ev, vst) => { let typ = match ev.node { 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) } 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 mut any_error = false; let mut any_bot = false; @@ -2164,7 +2164,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ast::expr_repeat(element, count_expr, mutbl) => { let count = ty::eval_repeat_count(tcx, count_expr); 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 { ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => { ast::m_mutbl @@ -3173,7 +3173,10 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, ast::def_upvar(_, 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"); } 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_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 // (if any) and otherwise using a fresh region variable 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, e: @ast::expr, - _n: uint, v: ast::expr_vstore) -> ty::vstore { match v { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 466cb8ed54f2..ab99aa20d648 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -38,7 +38,7 @@ use middle::typeck::infer::combine::Combine; use middle::typeck::infer::InferCtxt; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar}; 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; use syntax::ast_map::node_item; @@ -507,7 +507,7 @@ pub impl CoherenceChecker { 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 !f(method) { break; @@ -947,7 +947,7 @@ pub impl CoherenceChecker { crate_store, def_id); } - dl_def(def_ty(def_id)) => { + dl_def(def_trait(def_id)) => { let tcx = self.crate_context.tcx; let polytype = csearch::get_type(tcx, def_id); match ty::get(polytype.ty).sty { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index f1d743e79e58..d89d1c407d7b 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -53,7 +53,6 @@ use syntax::ast::{RegionTyParamBound, TraitTyParamBound}; use syntax::ast; use syntax::ast_map; use syntax::ast_util::{local_def, split_trait_methods}; -use syntax::ast_util::{trait_method_to_ty_method}; use syntax::ast_util; use syntax::codemap::span; use syntax::codemap; @@ -221,19 +220,61 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, } pub fn ensure_trait_methods(ccx: &CrateCtxt, - id: ast::node_id, - trait_ty: ty::t) { - fn store_methods(ccx: &CrateCtxt, - id: ast::node_id, - stuff: &[T], - f: &fn(v: &T) -> ty::method) { - ty::store_trait_methods(ccx.tcx, id, @stuff.map(f)); + trait_id: ast::node_id, + trait_ty: ty::t) +{ + let tcx = ccx.tcx; + let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x); + match *tcx.items.get(&trait_id) { + 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, - am: &ast::ty_method, rp: Option, - m: ty::method, + m: &ty::method, // Take this as an argument b/c we may check // the impl before the trait. trait_ty: ty::t, @@ -267,7 +308,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, ty::mk_bare_fn(ccx.tcx, copy m.fty)); let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]] + *m.tps); - ccx.tcx.tcache.insert(local_def(am.id), + ccx.tcx.tcache.insert(m.def_id, ty_param_bounds_and_ty { bounds: bounds, region_param: rp, @@ -275,40 +316,31 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, } - let tcx = ccx.tcx; - let region_paramd = tcx.region_paramd_items.find(&id).map_consume(|x| *x); - match *tcx.items.get(&id) { - ast_map::node_item(@ast::item { - node: ast::item_trait(ref generics, _, ref ms), - _ - }, _) => { - store_methods::(ccx, id, *ms, |m| { - let def_id; - match *m { - ast::required(ref ty_method) => { - def_id = local_def((*ty_method).id) - } - ast::provided(method) => def_id = local_def(method.id) - } - - let trait_bounds = ty_param_bounds(ccx, generics); - let ty_m = trait_method_to_ty_method(m); - let method_ty = ty_of_ty_method( - ccx, - &ty_m, - region_paramd, - def_id, - generics - ); - 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 */ } + fn ty_method_of_trait_method(self: &CrateCtxt, + trait_rp: Option, + trait_generics: &ast::Generics, + m_id: &ast::node_id, + m_ident: &ast::ident, + m_self_ty: &ast::self_ty, + m_generics: &ast::Generics, + m_purity: &ast::purity, + m_decl: &ast::fn_decl) -> ty::method + { + let rscope = MethodRscope::new(m_self_ty.node, trait_rp, trait_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: local_def(*m_id) + } } } @@ -501,8 +533,8 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt, rp: Option, selfty: ty::t, a_trait_ty: @ast::trait_ref, - impl_ms: &[ConvertedMethod]) { - + impl_ms: &[ConvertedMethod]) +{ let tcx = ccx.tcx; 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); for impl_ms.each |impl_m| { 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(); compare_impl_method( 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, - 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 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); 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); write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index afbf3f485d0a..238ecf7acea2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -443,7 +443,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { 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) => { let path = ty::item_path(cx, did); let base = ast_map::path_to_str(path, cx.sess.intr()); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2e7ae4c537a8..31dc476cbe49 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -194,6 +194,7 @@ pub enum def { def_local(node_id, bool /* is_mutbl */), def_variant(def_id /* enum */, def_id /* variant */), def_ty(def_id), + def_trait(def_id), def_prim_ty(prim_ty), def_ty_param(def_id, uint), def_binding(node_id, binding_mode), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 208ed1e35fe1..c7227fa17687 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -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_foreign_mod(id) | def_const(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 } def_arg(id, _, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id) diff --git a/src/test/compile-fail/extern-no-call.rs b/src/test/compile-fail/extern-no-call.rs index 8c6deb348167..58649f3209bb 100644 --- a/src/test/compile-fail/extern-no-call.rs +++ b/src/test/compile-fail/extern-no-call.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // 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() { } diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/compile-fail/issue-3563.rs index 0388f0fd2908..d56cb0d51d23 100644 --- a/src/test/compile-fail/issue-3563.rs +++ b/src/test/compile-fail/issue-3563.rs @@ -10,7 +10,7 @@ trait A { 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() {}