diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index ddd07c2cb2723..645188ce5a4d9 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -179,6 +179,8 @@ pub static tag_mod_child: uint = 0x7e; pub static tag_misc_info: uint = 0x7f; pub static tag_misc_info_crate_items: uint = 0x80; +pub static tag_item_method_provided_source: uint = 0x81; + pub struct LinkMeta { name: @str, vers: @str, diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index f336b0f4e4c5e..993649492a463 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -15,7 +15,7 @@ use metadata::common::*; use metadata::cstore; use metadata::decoder; use metadata; -use middle::{ty, resolve}; +use middle::ty; use std::vec; use reader = extra::ebml::reader; @@ -97,10 +97,10 @@ pub fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id) } /// Returns information about the given implementation. -pub fn get_impl(cstore: @mut cstore::CStore, impl_def_id: ast::def_id) - -> resolve::Impl { - let cdata = cstore::get_crate_data(cstore, impl_def_id.crate); - decoder::get_impl(cstore.intr, cdata, impl_def_id.node) +pub fn get_impl(tcx: ty::ctxt, impl_def_id: ast::def_id) + -> ty::Impl { + let cdata = cstore::get_crate_data(tcx.cstore, impl_def_id.crate); + decoder::get_impl(tcx.cstore.intr, cdata, impl_def_id.node, tcx) } pub fn get_method(tcx: ty::ctxt, def: ast::def_id) -> ty::Method { diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index caa170605dec3..a77c6c6ab5223 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -20,7 +20,7 @@ use metadata::decoder; use metadata::tydecode::{parse_ty_data, parse_def_id, parse_type_param_def_data, parse_bare_fn_ty_data, parse_trait_ref_data}; -use middle::{ty, resolve}; +use middle::ty; use std::hash::HashUtil; use std::int; @@ -174,14 +174,6 @@ fn item_parent_item(d: ebml::Doc) -> Option { None } -fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) -> - Option { - let trait_did_opt = item_parent_item(d); - do trait_did_opt.map |trait_did| { - ast::def_id { crate: cnum, node: trait_did.node } - } -} - fn item_reqd_and_translated_parent_item(cnum: ast::crate_num, d: ebml::Doc) -> ast::def_id { let trait_did = item_parent_item(d).expect("item without parent"); @@ -193,6 +185,12 @@ fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id { return translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id)); } +fn get_provided_source(d: ebml::Doc, cdata: cmd) -> Option { + do reader::maybe_get_doc(d, tag_item_method_provided_source).map |doc| { + translate_def_id(cdata, reader::with_doc_data(*doc, parse_def_id)) + } +} + fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) -> bool { for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| { if !f(reexport_doc) { @@ -323,13 +321,19 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), Fn => dl_def(ast::def_fn(did, ast::impure_fn)), ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), - UnsafeStaticMethod => { - let trait_did_opt = translated_parent_item_opt(cnum, item); - dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn)) - } - StaticMethod => { - let trait_did_opt = translated_parent_item_opt(cnum, item); - dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn)) + StaticMethod | UnsafeStaticMethod => { + let purity = if fam == UnsafeStaticMethod { ast::unsafe_fn } else + { ast::impure_fn }; + // def_static_method carries an optional field of its enclosing + // *trait*, but not an inclosing Impl (if this is an inherent + // static method). So we need to detect whether this is in + // a trait or not, which we do through the mildly hacky + // way of checking whether there is a trait_method_sort. + let trait_did_opt = if reader::maybe_get_doc( + item, tag_item_trait_method_sort).is_some() { + Some(item_reqd_and_translated_parent_item(cnum, item)) + } else { None }; + dl_def(ast::def_static_method(did, trait_did_opt, purity)) } Type | ForeignType => dl_def(ast::def_ty(did)), Mod => dl_def(ast::def_mod(did)), @@ -795,34 +799,29 @@ fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ { } fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc, - base_tps: uint) -> ~[@resolve::MethodInfo] { + tcx: ty::ctxt) -> ~[@ty::Method] { let mut rslt = ~[]; for reader::tagged_docs(item, tag_item_impl_method) |doc| { let m_did = reader::with_doc_data(doc, parse_def_id); - let mth_item = lookup_item(m_did.node, cdata.data); - let explicit_self = get_explicit_self(mth_item); - rslt.push(@resolve::MethodInfo { - did: translate_def_id(cdata, m_did), - n_tps: item_ty_param_count(mth_item) - base_tps, - ident: item_name(intr, mth_item), - explicit_self: explicit_self}); + rslt.push(@get_method(intr, cdata, m_did.node, tcx)); } + rslt } /// Returns information about the given implementation. -pub fn get_impl(intr: @ident_interner, cdata: cmd, impl_id: ast::node_id) - -> resolve::Impl { +pub fn get_impl(intr: @ident_interner, cdata: cmd, impl_id: ast::node_id, + tcx: ty::ctxt) + -> ty::Impl { let data = cdata.data; let impl_item = lookup_item(impl_id, data); - let base_tps = item_ty_param_count(impl_item); - resolve::Impl { + ty::Impl { did: ast::def_id { crate: cdata.cnum, node: impl_id, }, ident: item_name(intr, impl_item), - methods: item_impl_methods(intr, cdata, impl_item, base_tps), + methods: item_impl_methods(intr, cdata, impl_item, tcx), } } @@ -842,6 +841,8 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, { let method_doc = lookup_item(id, cdata.data); let def_id = item_def_id(method_doc, cdata); + let container_id = item_reqd_and_translated_parent_item(cdata.cnum, + method_doc); let name = item_name(intr, method_doc); let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata, tag_item_method_tps); @@ -849,6 +850,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, let fty = doc_method_fty(method_doc, tcx, cdata); let vis = item_visibility(method_doc); let explicit_self = get_explicit_self(method_doc); + let provided_source = get_provided_source(method_doc, cdata); ty::Method::new( name, @@ -860,7 +862,9 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, fty, explicit_self, vis, - def_id + def_id, + container_id, + provided_source ) } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index ab42e84e2acfe..2ef00a2167f01 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -15,10 +15,9 @@ use metadata::common::*; use metadata::cstore; use metadata::decoder; use metadata::tyencode; -use middle::ty::node_id_to_type; +use middle::ty::{node_id_to_type, lookup_item_type}; use middle::ty; use middle; -use util::ppaux::ty_to_str; use std::hash::HashUtil; use std::hashmap::{HashMap, HashSet}; @@ -37,8 +36,6 @@ use syntax::ast_map; use syntax::ast_util::*; use syntax::attr; use syntax::diagnostic::span_handler; -use syntax::opt_vec::OptVec; -use syntax::opt_vec; use syntax::parse::token::special_idents; use syntax::{ast_util, visit}; use syntax::parse::token; @@ -192,13 +189,12 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder, } } -fn encode_type_param_bounds(ebml_w: &mut writer::Encoder, - ecx: &EncodeContext, - params: &OptVec) { - let ty_param_defs = - @params.map_to_vec(|param| ecx.tcx.ty_param_defs.get_copy(¶m.id)); - encode_ty_type_param_defs(ebml_w, ecx, ty_param_defs, +fn encode_bounds_and_type(ebml_w: &mut writer::Encoder, + ecx: &EncodeContext, + tpt: &ty::ty_param_bounds_and_ty) { + encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs, tag_items_data_item_ty_param_bounds); + encode_type(ecx, ebml_w, tpt.ty); } fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: def_id) { @@ -321,15 +317,14 @@ fn encode_enum_variant_info(ecx: &EncodeContext, let vi = ty::enum_variants(ecx.tcx, ast::def_id { crate: local_crate, node: id }); for variants.iter().advance |variant| { + let def_id = local_def(variant.node.id); index.push(entry {val: variant.node.id, pos: ebml_w.writer.tell()}); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(variant.node.id)); + encode_def_id(ebml_w, def_id); encode_family(ebml_w, 'v'); encode_name(ecx, ebml_w, variant.node.name); encode_parent_item(ebml_w, local_def(id)); encode_visibility(ebml_w, variant.node.vis); - encode_type(ecx, ebml_w, - node_id_to_type(ecx.tcx, variant.node.id)); match variant.node.kind { ast::tuple_variant_kind(ref args) if args.len() > 0 && generics.ty_params.len() == 0 => { @@ -342,7 +337,8 @@ fn encode_enum_variant_info(ecx: &EncodeContext, encode_disr_val(ecx, ebml_w, vi[i].disr_val); disr_val = vi[i].disr_val; } - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); + encode_bounds_and_type(ebml_w, ecx, + &lookup_item_type(ecx.tcx, def_id)); encode_path(ecx, ebml_w, path, ast_map::path_name(variant.node.name)); ebml_w.end_tag(); @@ -396,13 +392,13 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, exp: &middle::resolve::Export2) -> bool { - match ecx.tcx.base_impls.find(&exp.def_id) { + match ecx.tcx.inherent_impls.find(&exp.def_id) { Some(implementations) => { for implementations.iter().advance |&base_impl| { for base_impl.methods.iter().advance |&m| { if m.explicit_self == ast::sty_static { encode_reexported_static_method(ecx, ebml_w, exp, - m.did, m.ident); + m.def_id, m.ident); } } } @@ -654,6 +650,16 @@ fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) { ebml_w.end_tag(); } +fn encode_provided_source(ebml_w: &mut writer::Encoder, + source_opt: Option) { + for source_opt.iter().advance |source| { + ebml_w.start_tag(tag_item_method_provided_source); + let s = def_to_str(*source); + ebml_w.writer.write(s.as_bytes()); + ebml_w.end_tag(); + } +} + /* Returns an index of items in this class */ fn encode_info_for_struct(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, @@ -689,36 +695,6 @@ fn encode_info_for_struct(ecx: &EncodeContext, index } -// This is for encoding info for ctors and dtors -fn encode_info_for_ctor(ecx: &EncodeContext, - ebml_w: &mut writer::Encoder, - id: node_id, - ident: ident, - path: &[ast_map::path_elt], - item: Option, - generics: &ast::Generics) { - ebml_w.start_tag(tag_items_data_item); - encode_name(ecx, ebml_w, ident); - encode_def_id(ebml_w, local_def(id)); - encode_family(ebml_w, purity_fn_family(ast::impure_fn)); - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - let its_ty = node_id_to_type(ecx.tcx, id); - debug!("fn name = %s ty = %s its node id = %d", - ecx.tcx.sess.str_of(ident), - ty_to_str(ecx.tcx, its_ty), id); - encode_type(ecx, ebml_w, its_ty); - encode_path(ecx, ebml_w, path, ast_map::path_name(ident)); - match item { - Some(it) => { - (ecx.encode_inlined_item)(ecx, ebml_w, path, it); - } - None => { - encode_symbol(ecx, ebml_w, id); - } - } - ebml_w.end_tag(); -} - fn encode_info_for_struct_ctor(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, path: &[ast_map::path_elt], @@ -753,52 +729,47 @@ fn encode_method_ty_fields(ecx: &EncodeContext, encode_method_fty(ecx, ebml_w, &method_ty.fty); encode_visibility(ebml_w, method_ty.vis); encode_explicit_self(ebml_w, method_ty.explicit_self); + let purity = method_ty.fty.purity; + match method_ty.explicit_self { + ast::sty_static => { + encode_family(ebml_w, purity_static_method_family(purity)); + } + _ => encode_family(ebml_w, purity_fn_family(purity)) + } + encode_provided_source(ebml_w, method_ty.provided_source); } fn encode_info_for_method(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, + m: &ty::Method, impl_path: &[ast_map::path_elt], - should_inline: bool, + is_default_impl: bool, parent_id: node_id, - m: @method, - owner_generics: &ast::Generics, - method_generics: &ast::Generics) { - debug!("encode_info_for_method: %d %s %u %u", m.id, - ecx.tcx.sess.str_of(m.ident), - owner_generics.ty_params.len(), - method_generics.ty_params.len()); + ast_method_opt: Option<@method>) { + + debug!("encode_info_for_method: %? %s", m.def_id, + ecx.tcx.sess.str_of(m.ident)); ebml_w.start_tag(tag_items_data_item); - let method_def_id = local_def(m.id); - let method_ty = ty::method(ecx.tcx, method_def_id); - encode_method_ty_fields(ecx, ebml_w, method_ty); + encode_method_ty_fields(ecx, ebml_w, m); + encode_parent_item(ebml_w, local_def(parent_id)); - match m.explicit_self.node { - ast::sty_static => { - encode_family(ebml_w, purity_static_method_family(m.purity)); - } - _ => encode_family(ebml_w, purity_fn_family(m.purity)) - } - - let mut combined_ty_params = opt_vec::Empty; - for owner_generics.ty_params.iter().advance |x| { - combined_ty_params.push((*x).clone()) - } - for method_generics.ty_params.iter().advance |x| { - combined_ty_params.push((*x).clone()) - } - let len = combined_ty_params.len(); - encode_type_param_bounds(ebml_w, ecx, &combined_ty_params); + // The type for methods gets encoded twice, which is unfortunate. + let tpt = lookup_item_type(ecx.tcx, m.def_id); + encode_bounds_and_type(ebml_w, ecx, &tpt); - encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id)); encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident)); - if len > 0u || should_inline { - (ecx.encode_inlined_item)( - ecx, ebml_w, impl_path, - ii_method(local_def(parent_id), false, m)); - } else { - encode_symbol(ecx, ebml_w, m.id); + for ast_method_opt.iter().advance |ast_method| { + let num_params = tpt.generics.type_param_defs.len(); + if num_params > 0u || is_default_impl + || should_inline(ast_method.attrs) { + (ecx.encode_inlined_item)( + ecx, ebml_w, impl_path, + ii_method(local_def(parent_id), false, *ast_method)); + } else { + encode_symbol(ecx, ebml_w, m.def_id.node); + } } ebml_w.end_tag(); @@ -844,11 +815,12 @@ fn encode_info_for_item(ecx: &EncodeContext, debug!("encoding info for item at %s", ecx.tcx.sess.codemap.span_to_str(item.span)); + let def_id = local_def(item.id); match item.node { item_static(_, m, _) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(item.id)); + encode_def_id(ebml_w, def_id); if m == ast::m_mutbl { encode_family(ebml_w, 'b'); } else { @@ -864,11 +836,10 @@ fn encode_info_for_item(ecx: &EncodeContext, item_fn(_, purity, _, ref generics, _) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(item.id)); + encode_def_id(ebml_w, def_id); encode_family(ebml_w, purity_fn_family(purity)); let tps_len = generics.ty_params.len(); - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); + encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(ecx, ebml_w, item.ident); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); encode_attributes(ebml_w, item.attrs); @@ -892,7 +863,7 @@ fn encode_info_for_item(ecx: &EncodeContext, item_foreign_mod(ref fm) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(item.id)); + encode_def_id(ebml_w, def_id); encode_family(ebml_w, 'n'); encode_name(ecx, ebml_w, item.ident); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); @@ -906,13 +877,12 @@ fn encode_info_for_item(ecx: &EncodeContext, ebml_w.end_tag(); } - item_ty(_, ref generics) => { + item_ty(*) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(item.id)); + encode_def_id(ebml_w, def_id); encode_family(ebml_w, 'y'); - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); + encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(ecx, ebml_w, item.ident); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); encode_region_param(ecx, ebml_w, item); @@ -922,10 +892,9 @@ fn encode_info_for_item(ecx: &EncodeContext, add_to_index(); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(item.id)); + encode_def_id(ebml_w, def_id); encode_family(ebml_w, 't'); - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); + encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(ecx, ebml_w, item.ident); for (*enum_definition).variants.iter().advance |v| { encode_variant_id(ebml_w, local_def(v.node.id)); @@ -943,7 +912,7 @@ fn encode_info_for_item(ecx: &EncodeContext, index, generics); } - item_struct(struct_def, ref generics) => { + item_struct(struct_def, _) => { /* First, encode the fields These come first because we need to write them to make the index, and the index needs to be in the item for the @@ -956,10 +925,9 @@ fn encode_info_for_item(ecx: &EncodeContext, /* Now, make an item for the class itself */ ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(item.id)); + encode_def_id(ebml_w, def_id); encode_family(ebml_w, 'S'); - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); + encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); @@ -1008,14 +976,17 @@ fn encode_info_for_item(ecx: &EncodeContext, index); } } - item_impl(ref generics, ref opt_trait, ref ty, ref methods) => { + item_impl(_, ref opt_trait, ref ty, ref ast_methods) => { + // We need to encode information about the default methods we + // have inherited, so we drive this based on the impl structure. + let imp = tcx.impls.get(&def_id); + add_to_index(); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(item.id)); + encode_def_id(ebml_w, def_id); encode_family(ebml_w, 'i'); encode_region_param(ecx, ebml_w, item); - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); + encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); match ty.node { @@ -1026,15 +997,15 @@ fn encode_info_for_item(ecx: &EncodeContext, } _ => {} } - for methods.iter().advance |m| { + for imp.methods.iter().advance |method| { ebml_w.start_tag(tag_item_impl_method); - let method_def_id = local_def(m.id); - let s = def_to_str(method_def_id); + let s = def_to_str(method.def_id); ebml_w.writer.write(s.as_bytes()); ebml_w.end_tag(); } for opt_trait.iter().advance |ast_trait_ref| { - let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id); + let trait_ref = ty::node_id_to_trait_ref( + tcx, ast_trait_ref.ref_id); encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref); } encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); @@ -1044,30 +1015,40 @@ fn encode_info_for_item(ecx: &EncodeContext, let mut impl_path = vec::append(~[], path); impl_path.push(ast_map::path_name(item.ident)); - for methods.iter().advance |m| { - index.push(entry {val: m.id, pos: ebml_w.writer.tell()}); + // Iterate down the methods, emitting them. We rely on the + // assumption that all of the actually implemented methods + // appear first in the impl structure, in the same order they do + // in the ast. This is a little sketchy. + let num_implemented_methods = ast_methods.len(); + for imp.methods.iter().enumerate().advance |(i, m)| { + let ast_method = if i < num_implemented_methods { + Some(ast_methods[i]) + } else { None }; + + index.push(entry {val: m.def_id.node, pos: ebml_w.writer.tell()}); encode_info_for_method(ecx, ebml_w, + *m, impl_path, - should_inline(m.attrs), + false, item.id, - *m, - generics, - &m.generics); + ast_method) } } - item_trait(ref generics, ref super_traits, ref ms) => { + item_trait(_, ref super_traits, ref ms) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(item.id)); + encode_def_id(ebml_w, def_id); encode_family(ebml_w, 'I'); encode_region_param(ecx, ebml_w, item); - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - let trait_def = ty::lookup_trait_def(tcx, local_def(item.id)); + let trait_def = ty::lookup_trait_def(tcx, def_id); + encode_ty_type_param_defs(ebml_w, ecx, + trait_def.generics.type_param_defs, + tag_items_data_item_ty_param_bounds); encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref); encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); - for ty::trait_method_def_ids(tcx, local_def(item.id)).iter().advance |&method_def_id| { + for ty::trait_method_def_ids(tcx, def_id).iter().advance |&method_def_id| { ebml_w.start_tag(tag_item_trait_method); encode_def_id(ebml_w, method_def_id); ebml_w.end_tag(); @@ -1084,7 +1065,7 @@ fn encode_info_for_item(ecx: &EncodeContext, ebml_w.end_tag(); // Now output the method info for each method. - let r = ty::trait_method_def_ids(tcx, local_def(item.id)); + let r = ty::trait_method_def_ids(tcx, def_id); for r.iter().enumerate().advance |(i, &method_def_id)| { assert_eq!(method_def_id.crate, ast::local_crate); @@ -1096,7 +1077,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_method_ty_fields(ecx, ebml_w, method_ty); - encode_parent_item(ebml_w, local_def(item.id)); + encode_parent_item(ebml_w, def_id); let mut trait_path = vec::append(~[], path); trait_path.push(ast_map::path_name(item.ident)); @@ -1109,10 +1090,7 @@ fn encode_info_for_item(ecx: &EncodeContext, method_ty.fty.purity)); let tpt = ty::lookup_item_type(tcx, method_def_id); - encode_ty_type_param_defs(ebml_w, ecx, - tpt.generics.type_param_defs, - tag_items_data_item_ty_param_bounds); - encode_type(ecx, ebml_w, tpt.ty); + encode_bounds_and_type(ebml_w, ecx, &tpt); } _ => { @@ -1131,13 +1109,14 @@ fn encode_info_for_item(ecx: &EncodeContext, // If this is a static method, we've already encoded // this. if method_ty.explicit_self != sty_static { - encode_type_param_bounds(ebml_w, ecx, - &m.generics.ty_params); + // XXX: I feel like there is something funny going on. + let tpt = ty::lookup_item_type(tcx, method_def_id); + encode_bounds_and_type(ebml_w, ecx, &tpt); } encode_method_sort(ebml_w, 'p'); (ecx.encode_inlined_item)( ecx, ebml_w, path, - ii_method(local_def(item.id), true, m)); + ii_method(def_id, true, m)); } } @@ -1158,11 +1137,11 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, ebml_w.start_tag(tag_items_data_item); match nitem.node { - foreign_item_fn(_, purity, ref generics) => { + foreign_item_fn(_, purity, _) => { encode_def_id(ebml_w, local_def(nitem.id)); encode_family(ebml_w, purity_fn_family(purity)); - encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id)); + encode_bounds_and_type(ebml_w, ecx, + &lookup_item_type(ecx.tcx,local_def(nitem.id))); encode_name(ecx, ebml_w, nitem.ident); if abi.is_intrinsic() { (ecx.encode_inlined_item)(ecx, ebml_w, *path, ii_foreign(nitem)); diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 036c075148343..c602a14325307 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -106,29 +106,6 @@ pub fn check_crate<'mm>(tcx: ty::ctxt, } }; - // Returns the ID of the container (impl or trait) that a crate-local - // method belongs to. - let local_method_container_id: - @fn(span: span, method_id: node_id) -> def_id = - |span, method_id| { - match tcx.items.find(&method_id) { - Some(&node_method(_, impl_id, _)) => impl_id, - Some(&node_trait_method(_, trait_id, _)) => trait_id, - Some(_) => { - tcx.sess.span_bug(span, - fmt!("method was a %s?!", - ast_map::node_id_to_str( - tcx.items, - method_id, - token::get_ident_interner()))); - } - None => { - tcx.sess.span_bug(span, "method not found in \ - AST map?!"); - } - } - }; - // Returns true if a crate-local method is private and false otherwise. let method_is_private: @fn(span: span, method_id: node_id) -> bool = |span, method_id| { @@ -248,15 +225,12 @@ pub fn check_crate<'mm>(tcx: ty::ctxt, // If the method is a default method, we need to use the def_id of // the default implementation. // Having to do this this is really unfortunate. - let method_id = match tcx.provided_method_sources.find(&method_id) { - None => method_id, - Some(source) => source.method_id - }; + let method_id = ty::method(tcx, method_id).provided_source + .get_or_default(method_id); if method_id.crate == local_crate { let is_private = method_is_private(span, method_id.node); - let container_id = local_method_container_id(span, - method_id.node); + let container_id = ty::method(tcx, method_id).container_id; if is_private && (container_id.crate != local_crate || !privileged_items.iter().any(|x| x == &(container_id.node))) { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 80078eba23936..6d457b46d4f3d 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -55,24 +55,6 @@ pub struct binding_info { // Map from the name in a pattern to its binding mode. pub type BindingMap = HashMap; -// Implementation resolution -// -// FIXME #4946: This kind of duplicates information kept in -// ty::method. Maybe it should go away. - -pub struct MethodInfo { - did: def_id, - n_tps: uint, - ident: ident, - explicit_self: explicit_self_ -} - -pub struct Impl { - did: def_id, - ident: ident, - methods: ~[@MethodInfo] -} - // Trait method resolution pub type TraitMap = HashMap; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 588b0b5c75f48..6741637ae9ab3 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -524,7 +524,6 @@ pub fn get_res_dtor(ccx: @mut CrateContext, &tsubsts, None, None, - None, None); val diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 0885c5086e857..f03a2a62e0c16 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -296,10 +296,10 @@ pub fn trans_fn_ref_with_vtables( // We need to do a bunch of special handling for default methods. // We need to modify the def_id and our substs in order to monomorphize // the function. - let (def_id, opt_impl_did, substs, self_vtable, vtables) = - match tcx.provided_method_sources.find(&def_id) { - None => (def_id, None, substs, None, vtables), - Some(source) => { + let (is_default, def_id, substs, self_vtable, vtables) = + match ty::provided_source(tcx, def_id) { + None => (false, def_id, substs, None, vtables), + Some(source_id) => { // There are two relevant substitutions when compiling // default methods. First, there is the substitution for // the type parameters of the impl we are using and the @@ -313,10 +313,11 @@ pub fn trans_fn_ref_with_vtables( // So, what we need to do is find this substitution and // compose it with the one we already have. - let trait_ref = ty::impl_trait_ref(tcx, source.impl_id) + let impl_id = ty::method(tcx, def_id).container_id; + let method = ty::method(tcx, source_id); + let trait_ref = ty::impl_trait_ref(tcx, impl_id) .expect("could not find trait_ref for impl with \ default methods"); - let method = ty::method(tcx, source.method_id); // Get all of the type params for the receiver let param_defs = method.generics.type_param_defs; @@ -330,18 +331,18 @@ pub fn trans_fn_ref_with_vtables( }; let self_vtable = - typeck::vtable_static(source.impl_id, receiver_substs, + typeck::vtable_static(impl_id, receiver_substs, receiver_vtables); // Compute the first substitution let first_subst = make_substs_for_receiver_types( - tcx, source.impl_id, trait_ref, method); + tcx, impl_id, trait_ref, method); // And compose them let new_substs = first_subst.subst(tcx, &substs); let vtables = - resolve_default_method_vtables(bcx, source.impl_id, + resolve_default_method_vtables(bcx, impl_id, method, &new_substs, vtables); debug!("trans_fn_with_vtables - default method: \ @@ -352,7 +353,7 @@ pub fn trans_fn_ref_with_vtables( first_subst.repr(tcx), new_substs.repr(tcx), self_vtable.repr(tcx), vtables.repr(tcx)); - (source.method_id, Some(source.impl_id), + (true, source_id, new_substs, Some(self_vtable), Some(vtables)) } }; @@ -372,7 +373,7 @@ pub fn trans_fn_ref_with_vtables( // intrinsic that is inlined from a different crate, we want to reemit the // intrinsic instead of trying to call it in the other crate. let must_monomorphise; - if type_params.len() > 0 || opt_impl_did.is_some() { + if type_params.len() > 0 || is_default { must_monomorphise = true; } else if def_id.crate == ast::local_crate { let map_node = session::expect( @@ -400,7 +401,7 @@ pub fn trans_fn_ref_with_vtables( let (val, must_cast) = monomorphize::monomorphic_fn(ccx, def_id, &substs, vtables, self_vtable, - opt_impl_did, Some(ref_id)); + Some(ref_id)); let mut val = val; if must_cast && ref_id != 0 { // Monotype of the REFERENCE to the function (type params diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 29cc8d8197317..d90614ebc021c 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -938,8 +938,7 @@ pub fn mono_data_classify(t: ty::t) -> MonoDataClass { #[deriving(Eq,IterBytes)] pub struct mono_id_ { def: ast::def_id, - params: ~[mono_param_id], - impl_did_opt: Option + params: ~[mono_param_id] } pub type mono_id = @mono_id_; diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 4ca8057f3889d..bcf3aa6ad50bf 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -162,7 +162,7 @@ pub fn trans_method_callee(bcx: block, let self_ty = node_id_type(bcx, this.id); // is the ID of the implementation of // trait for type - let impl_id = ty::get_impl_id(tcx, trait_id, self_ty); + let impl_id = ty::bogus_get_impl_id_from_ty(tcx, trait_id, self_ty); // Get the supertrait's methods let supertrait_method_def_ids = ty::trait_method_def_ids(tcx, trait_id); // Make sure to fail with a readable error message if @@ -177,9 +177,7 @@ pub fn trans_method_callee(bcx: block, // Now that we know the impl ID, we can look up the method // ID from its name origin = typeck::method_static( - method_with_name_or_default(bcx.ccx(), - impl_id, - method_name)); + method_with_name(bcx.ccx(), impl_id, method_name)); } typeck::method_self(*) | typeck::method_static(*) | typeck::method_param(*) | @@ -308,12 +306,10 @@ pub fn trans_static_method_callee(bcx: block, typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t))); - let mth_id = method_with_name_or_default(bcx.ccx(), - impl_did, - mname); + let mth_id = method_with_name(bcx.ccx(), impl_did, mname); let (callee_substs, callee_origins) = combine_impl_and_methods_tps( - bcx, mth_id, impl_did, callee_id, + bcx, mth_id, callee_id, *rcvr_substs, rcvr_origins); let FnData {llfn: lval} = @@ -334,58 +330,22 @@ pub fn trans_static_method_callee(bcx: block, } } -pub fn method_from_methods(ms: &[@ast::method], name: ast::ident) - -> Option { - ms.iter().find_(|m| m.ident == name).map(|m| ast_util::local_def(m.id)) -} - -pub fn method_with_name_or_default(ccx: &mut CrateContext, - impl_id: ast::def_id, - name: ast::ident) -> ast::def_id { - let imp = ccx.impl_method_cache.find_copy(&(impl_id, name)); - match imp { +pub fn method_with_name(ccx: &mut CrateContext, + impl_id: ast::def_id, + name: ast::ident) -> ast::def_id { + let meth_id_opt = ccx.impl_method_cache.find_copy(&(impl_id, name)); + match meth_id_opt { Some(m) => return m, None => {} } - // None of this feels like it should be the best way to do this. - let mut did = if impl_id.crate == ast::local_crate { - match ccx.tcx.items.get_copy(&impl_id.node) { - ast_map::node_item(@ast::item { - node: ast::item_impl(_, _, _, ref ms), _ - }, _) => { method_from_methods(*ms, name) }, - _ => fail!("method_with_name") - } - } else { - csearch::get_impl_method(ccx.sess.cstore, impl_id, name) - }; - - if did.is_none() { - // Look for a default method - let pmm = ccx.tcx.provided_methods; - match pmm.find(&impl_id) { - Some(pmis) => { - for pmis.iter().advance |pmi| { - if pmi.method_info.ident == name { - debug!("pmi.method_info.did = %?", - pmi.method_info.did); - did = Some(pmi.method_info.did); - } - } - } - None => {} - } - } - - let imp = did.expect("could not find method while translating"); - ccx.impl_method_cache.insert((impl_id, name), imp); - imp -} + let imp = ccx.tcx.impls.find(&impl_id) + .expect("could not find impl while translating"); + let meth = imp.methods.iter().find_(|m| m.ident == name) + .expect("could not find method while translating"); -pub fn method_ty_param_count(ccx: &CrateContext, m_id: ast::def_id, - i_id: ast::def_id) -> uint { - debug!("method_ty_param_count: m_id: %?, i_id: %?", m_id, i_id); - ty::method(ccx.tcx, m_id).generics.type_param_defs.len() + ccx.impl_method_cache.insert((impl_id, name), meth.def_id); + meth.def_id } pub fn trans_monomorphized_callee(bcx: block, @@ -401,8 +361,7 @@ pub fn trans_monomorphized_callee(bcx: block, typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { let ccx = bcx.ccx(); 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); + let mth_id = method_with_name(bcx.ccx(), impl_did, mname); // obtain the `self` value: let mut temp_cleanups = ~[]; @@ -413,7 +372,7 @@ pub fn trans_monomorphized_callee(bcx: block, // those from the impl and those from the method: let (callee_substs, callee_origins) = combine_impl_and_methods_tps( - bcx, mth_id, impl_did, callee_id, + bcx, mth_id, callee_id, *rcvr_substs, rcvr_origins); // translate the function @@ -452,7 +411,6 @@ pub fn trans_monomorphized_callee(bcx: block, pub fn combine_impl_and_methods_tps(bcx: block, mth_did: ast::def_id, - impl_did: ast::def_id, callee_id: ast::node_id, rcvr_substs: &[ty::t], rcvr_origins: typeck::vtable_res) @@ -475,15 +433,16 @@ pub fn combine_impl_and_methods_tps(bcx: block, * mapped to. */ let ccx = bcx.ccx(); - let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did); + let method = ty::method(ccx.tcx, mth_did); + let n_m_tps = method.generics.type_param_defs.len(); let node_substs = node_id_type_params(bcx, callee_id); - debug!("rcvr_substs=%?", rcvr_substs.map(|t| bcx.ty_to_str(*t))); + debug!("rcvr_substs=%?", rcvr_substs.repr(ccx.tcx)); let ty_substs = vec::append(rcvr_substs.to_owned(), node_substs.tailn(node_substs.len() - n_m_tps)); debug!("n_m_tps=%?", n_m_tps); - debug!("node_substs=%?", node_substs.map(|t| bcx.ty_to_str(*t))); - debug!("ty_substs=%?", ty_substs.map(|t| bcx.ty_to_str(*t))); + debug!("node_substs=%?", node_substs.repr(ccx.tcx)); + debug!("ty_substs=%?", ty_substs.repr(ccx.tcx)); // Now, do the same work for the vtables. The vtables might not @@ -658,7 +617,6 @@ pub fn vtable_id(ccx: @mut CrateContext, monomorphize::make_mono_id( ccx, impl_id, - None, &psubsts, None) } @@ -744,7 +702,7 @@ pub fn make_impl_vtable(bcx: block, } else { debug!("(making impl vtable) adding method to vtable: %s", tcx.sess.str_of(im.ident)); - let m_id = method_with_name_or_default(ccx, impl_id, im.ident); + let m_id = method_with_name(ccx, impl_id, im.ident); trans_fn_ref_with_vtables(bcx, m_id, 0, substs, Some(vtables)).llfn diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 3e5f72679724b..789532abc611f 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -42,7 +42,6 @@ pub fn monomorphic_fn(ccx: @mut CrateContext, real_substs: &ty::substs, vtables: Option, self_vtable: Option, - impl_did_opt: Option, ref_id: Option) -> (ValueRef, bool) { @@ -51,13 +50,11 @@ pub fn monomorphic_fn(ccx: @mut CrateContext, real_substs=%s, \ vtables=%s, \ self_vtable=%s, \ - impl_did_opt=%s, \ ref_id=%?)", fn_id.repr(ccx.tcx), real_substs.repr(ccx.tcx), vtables.repr(ccx.tcx), self_vtable.repr(ccx.tcx), - impl_did_opt.repr(ccx.tcx), ref_id); assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t))); @@ -83,9 +80,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext, let param_uses = type_use::type_uses_for(ccx, fn_id, psubsts.tys.len()); - let hash_id = make_mono_id(ccx, fn_id, impl_did_opt, - &*psubsts, - Some(param_uses)); + let hash_id = make_mono_id(ccx, fn_id, &*psubsts, Some(param_uses)); if hash_id.params.iter().any( |p| match *p { mono_precise(_, _) => false, _ => true }) { must_cast = true; @@ -367,7 +362,6 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, pub fn make_mono_id(ccx: @mut CrateContext, item: ast::def_id, - impl_did_opt: Option, substs: ¶m_substs, param_uses: Option<@~[type_use::type_uses]>) -> mono_id { // FIXME (possibly #5801): Need a lot of type hints to get @@ -442,5 +436,5 @@ pub fn make_mono_id(ccx: @mut CrateContext, }).collect() } }; - @mono_id_ {def: item, params: param_ids, impl_did_opt: impl_did_opt} + @mono_id_ {def: item, params: param_ids} } diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 2c63079ad8f82..53c290ec0290d 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -90,7 +90,7 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint) // used. This is imprecise, but simple. Getting it right is // tricky because the substs on the call and the substs on the // default method differ, because of substs on the trait/impl. - let is_default = ccx.tcx.provided_method_sources.contains_key(&fn_id_loc); + let is_default = ty::provided_source(ccx.tcx, fn_id_loc).is_some(); // We also mark all of the params as used if it is an extern thing // that we haven't been able to inline yet. if is_default || fn_id_loc.crate != local_crate { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 50f331f7e7d48..b63117d25bb77 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -16,7 +16,6 @@ use middle::const_eval; use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem}; use middle::lang_items::OpaqueStructLangItem; use middle::freevars; -use middle::resolve::{Impl, MethodInfo}; use middle::resolve; use middle::ty; use middle::subst::Subst; @@ -65,7 +64,11 @@ pub struct Method { fty: BareFnTy, explicit_self: ast::explicit_self_, vis: ast::visibility, - def_id: ast::def_id + def_id: ast::def_id, + container_id: ast::def_id, + + // If this method is provided, we need to know where it came from + provided_source: Option } impl Method { @@ -75,7 +78,9 @@ impl Method { fty: BareFnTy, explicit_self: ast::explicit_self_, vis: ast::visibility, - def_id: ast::def_id) + def_id: ast::def_id, + container_id: ast::def_id, + provided_source: Option) -> Method { // Check the invariants. if explicit_self == ast::sty_static { @@ -91,11 +96,19 @@ impl Method { fty: fty, explicit_self: explicit_self, vis: vis, - def_id: def_id + def_id: def_id, + container_id: container_id, + provided_source: provided_source } } } +pub struct Impl { + did: def_id, + ident: ident, + methods: ~[@Method] +} + #[deriving(Clone, Eq, IterBytes)] pub struct mt { ty: t, @@ -214,26 +227,6 @@ pub enum AutoRef { AutoUnsafe(ast::mutability) } -// Stores information about provided methods (a.k.a. default methods) in -// implementations. -// -// This is a map from ID of each implementation to the method info and trait -// method ID of each of the default methods belonging to the trait that -// implementation implements. -pub type ProvidedMethodsMap = @mut HashMap; - -// Stores the method info and definition ID of the associated trait method for -// each instantiation of each provided method. -pub struct ProvidedMethodInfo { - method_info: @MethodInfo, - trait_method_def_id: def_id -} - -pub struct ProvidedMethodSource { - method_id: ast::def_id, - impl_id: ast::def_id -} - pub type ctxt = @ctxt_; struct ctxt_ { @@ -287,11 +280,8 @@ struct ctxt_ { adjustments: @mut HashMap, normalized_cache: @mut HashMap, lang_items: middle::lang_items::LanguageItems, - // A mapping from an implementation ID to the method info and trait - // method ID of the provided (a.k.a. default) methods in the traits that - // that implementation implements. - provided_methods: ProvidedMethodsMap, - provided_method_sources: @mut HashMap, + // A mapping of fake provided method def_ids to the default implementation + provided_method_sources: @mut HashMap, supertraits: @mut HashMap, // A mapping from the def ID of an enum or struct type to the def ID @@ -303,11 +293,19 @@ struct ctxt_ { // A method will be in this list if and only if it is a destructor. destructors: @mut HashSet, - // Maps a trait onto a mapping from self-ty to impl - trait_impls: @mut HashMap>, + // Maps a trait onto a list of impls of that trait. + trait_impls: @mut HashMap, - // Maps a base type to its impl - base_impls: @mut HashMap, + // Maps a def_id of a type to a list of its inherent impls. + // Contains implementations of methods that are inherent to a type. + // Methods in these implementations don't need to be exported. + inherent_impls: @mut HashMap, + + // Maps a def_id of an impl to an Impl structure. + // Note that this contains all of the impls that we know about, + // including ones in other crates. It's not clear that this is the best + // way to do it. + impls: @mut HashMap, // Set of used unsafe nodes (functions or blocks). Unsafe nodes not // present in this set can be warned about. @@ -902,13 +900,13 @@ pub fn mk_ctxt(s: session::Session, adjustments: @mut HashMap::new(), normalized_cache: new_ty_hash(), lang_items: lang_items, - provided_methods: @mut HashMap::new(), provided_method_sources: @mut HashMap::new(), supertraits: @mut HashMap::new(), destructor_for_type: @mut HashMap::new(), destructors: @mut HashSet::new(), trait_impls: @mut HashMap::new(), - base_impls: @mut HashMap::new(), + inherent_impls: @mut HashMap::new(), + impls: @mut HashMap::new(), used_unsafe: @mut HashSet::new(), used_mut_nodes: @mut HashSet::new(), } @@ -3516,6 +3514,11 @@ pub fn def_has_ty_params(def: ast::def) -> bool { } } +pub fn provided_source(cx: ctxt, id: ast::def_id) + -> Option { + cx.provided_method_sources.find(&id).map(|x| **x) +} + pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@Method] { if is_local(id) { match cx.items.find(&id.node) { @@ -3596,20 +3599,6 @@ pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method { } -pub fn add_base_impl(cx: ctxt, base_def_id: def_id, implementation: @Impl) { - let implementations; - match cx.base_impls.find(&base_def_id) { - None => { - implementations = @mut ~[]; - cx.base_impls.insert(base_def_id, implementations); - } - Some(&existing) => { - implementations = existing; - } - } - implementations.push(implementation); -} - pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] { match cx.trait_methods_cache.find(&trait_did) { Some(&methods) => methods, @@ -4375,16 +4364,25 @@ pub fn count_traits_and_supertraits(tcx: ctxt, return total; } -// Given a trait and a type, returns the impl of that type -pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id { +// Given a trait and a type, returns the impl of that type. +// This is broken, of course, by parametric impls. This used to use +// a table specifically for this mapping, but I removed that table. +// This is only used when calling a supertrait method from a default method, +// and should go away once I fix how that works. -sully +pub fn bogus_get_impl_id_from_ty(tcx: ctxt, + trait_id: def_id, self_ty: t) -> def_id { match tcx.trait_impls.find(&trait_id) { - Some(ty_to_impl) => match ty_to_impl.find(&self_ty) { - Some(the_impl) => the_impl.did, - None => // try autoderef! - match deref(tcx, self_ty, false) { - Some(some_ty) => get_impl_id(tcx, trait_id, some_ty.ty), - None => tcx.sess.bug("get_impl_id: no impl of trait for \ - this type") + Some(ty_to_impl) => { + for ty_to_impl.iter().advance |imp| { + let impl_ty = tcx.tcache.get_copy(&imp.did); + if impl_ty.ty == self_ty { return imp.did; } + } + // try autoderef! + match deref(tcx, self_ty, false) { + Some(some_ty) => + bogus_get_impl_id_from_ty(tcx, trait_id, some_ty.ty), + None => tcx.sess.bug("get_impl_id: no impl of trait for \ + this type") } }, None => tcx.sess.bug("get_impl_id: trait isn't in trait_impls") diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index d2a11953af056..4a32e8bf952c1 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -330,8 +330,7 @@ impl<'self> LookupContext<'self> { for opt_applicable_traits.iter().advance |applicable_traits| { for applicable_traits.iter().advance |trait_did| { // Look for explicit implementations. - let opt_impl_infos = - self.fcx.ccx.coherence_info.extension_methods.find(trait_did); + let opt_impl_infos = self.tcx().trait_impls.find(trait_did); for opt_impl_infos.iter().advance |impl_infos| { for impl_infos.iter().advance |impl_info| { self.push_candidates_from_impl( @@ -517,8 +516,7 @@ impl<'self> LookupContext<'self> { } pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) { - let opt_impl_infos = - self.fcx.ccx.coherence_info.inherent_methods.find(&did); + let opt_impl_infos = self.tcx().inherent_impls.find(&did); for opt_impl_infos.iter().advance |impl_infos| { for impl_infos.iter().advance |impl_info| { self.push_candidates_from_impl( @@ -529,7 +527,7 @@ impl<'self> LookupContext<'self> { pub fn push_candidates_from_impl(&self, candidates: &mut ~[Candidate], - impl_info: &resolve::Impl) { + impl_info: &ty::Impl) { if !self.impl_dups.insert(impl_info.did) { return; // already visited } @@ -545,7 +543,7 @@ impl<'self> LookupContext<'self> { } }; - let method = ty::method(self.tcx(), impl_info.methods[idx].did); + let method = ty::method(self.tcx(), impl_info.methods[idx].def_id); // determine the `self` of the impl with fresh // variables for each parameter: diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index d9036c72db659..6af0be48e47d8 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -260,7 +260,7 @@ fn lookup_vtable(vcx: &VtableContext, let mut impls_seen = HashSet::new(); - match vcx.ccx.coherence_info.extension_methods.find(&trait_ref.def_id) { + match tcx.trait_impls.find(&trait_ref.def_id) { None => { // Nothing found. Continue. } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 3a4154d7c50e2..c822536586453 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -17,10 +17,9 @@ use metadata::csearch::{each_path, get_impl_trait}; use metadata::csearch; -use metadata::cstore::{CStore, iter_crate_data}; +use metadata::cstore::iter_crate_data; use metadata::decoder::{dl_def, dl_field, dl_impl}; -use middle::resolve::{Impl, MethodInfo}; -use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, get}; +use middle::ty::get; use middle::ty::{lookup_item_type, subst}; use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err}; use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil}; @@ -31,6 +30,7 @@ use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec}; use middle::ty::{type_is_ty_var}; use middle::subst::Subst; use middle::ty; +use middle::ty::{Impl, Method}; use middle::typeck::CrateCtxt; use middle::typeck::infer::combine::Combine; use middle::typeck::infer::InferCtxt; @@ -38,7 +38,7 @@ use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type}; use middle::typeck::infer; use syntax::ast::{crate, def_id, def_struct, def_ty}; use syntax::ast::{item, item_enum, item_impl, item_mod, item_struct}; -use syntax::ast::{local_crate, method, trait_ref, ty_path}; +use syntax::ast::{local_crate, trait_ref, ty_path}; use syntax::ast; use syntax::ast_map::node_item; use syntax::ast_map; @@ -149,33 +149,6 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt, } } - -pub fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo { - @MethodInfo { - did: local_def(ast_method.id), - n_tps: ast_method.generics.ty_params.len(), - ident: ast_method.ident, - explicit_self: ast_method.explicit_self.node - } -} - -pub struct CoherenceInfo { - // Contains implementations of methods that are inherent to a type. - // Methods in these implementations don't need to be exported. - inherent_methods: @mut HashMap, - - // Contains implementations of methods associated with a trait. For these, - // the associated trait must be imported at the call site. - extension_methods: @mut HashMap, -} - -pub fn CoherenceInfo() -> CoherenceInfo { - CoherenceInfo { - inherent_methods: @mut HashMap::new(), - extension_methods: @mut HashMap::new(), - } -} - pub fn CoherenceChecker(crate_context: @mut CrateCtxt) -> CoherenceChecker { CoherenceChecker { crate_context: crate_context, @@ -267,27 +240,16 @@ impl CoherenceChecker { } } - // We only want to generate one Impl structure. When we generate one, - // we store it here so that we don't recreate it. - let mut implementation_opt = None; + let implementation = self.create_impl_from_item(item); + for associated_traits.iter().advance |associated_trait| { - let trait_ref = - ty::node_id_to_trait_ref( - self.crate_context.tcx, - associated_trait.ref_id); + let trait_ref = ty::node_id_to_trait_ref( + self.crate_context.tcx, associated_trait.ref_id); debug!("(checking implementation) adding impl for trait '%s', item '%s'", trait_ref.repr(self.crate_context.tcx), self.crate_context.tcx.sess.str_of(item.ident)); - self.instantiate_default_methods(local_def(item.id), trait_ref); - - let implementation; - if implementation_opt.is_none() { - implementation = self.create_impl_from_item(item); - implementation_opt = Some(implementation); - } - - self.add_trait_method(trait_ref.def_id, implementation_opt.get()); + self.add_trait_impl(trait_ref.def_id, implementation); } // Add the implementation to the mapping from implementation to base @@ -302,25 +264,15 @@ impl CoherenceChecker { Some(base_type_def_id) => { // XXX: Gather up default methods? if associated_traits.len() == 0 { - let implementation; - match implementation_opt { - None => { - implementation = - self.create_impl_from_item(item); - } - Some(existing_implementation) => { - implementation = existing_implementation; - } - } - - self.add_inherent_method(base_type_def_id, - implementation); + self.add_inherent_impl(base_type_def_id, implementation); } self.base_type_def_ids.insert(local_def(item.id), base_type_def_id); } } + + tcx.impls.insert(implementation.did, implementation); } // Creates default method IDs and performs type substitutions for an impl @@ -328,7 +280,8 @@ impl CoherenceChecker { // `ProvidedMethodInfo` instance into the `provided_method_sources` map. pub fn instantiate_default_methods(&self, impl_id: ast::def_id, - trait_ref: &ty::TraitRef) { + trait_ref: &ty::TraitRef, + all_methods: &mut ~[@Method]) { let tcx = self.crate_context.tcx; debug!("instantiate_default_methods(impl_id=%?, trait_ref=%s)", impl_id, trait_ref.repr(tcx)); @@ -350,9 +303,11 @@ impl CoherenceChecker { impl_id, trait_ref, new_did, - *trait_method); + *trait_method, + Some(trait_method.def_id)); debug!("new_method_ty=%s", new_method_ty.repr(tcx)); + all_methods.push(new_method_ty); // construct the polytype for the method based on the method_ty let new_generics = ty::Generics { @@ -374,60 +329,20 @@ impl CoherenceChecker { // Pair the new synthesized ID up with the // ID of the method. - let source = ProvidedMethodSource { - method_id: trait_method.def_id, - impl_id: impl_id - }; - - self.crate_context.tcx.provided_method_sources.insert(new_did, - source); - - let provided_method_info = - @ProvidedMethodInfo { - method_info: @MethodInfo { - did: new_did, - n_tps: trait_method.generics.type_param_defs.len(), - ident: trait_method.ident, - explicit_self: trait_method.explicit_self - }, - trait_method_def_id: trait_method.def_id - }; - - let pmm = self.crate_context.tcx.provided_methods; - match pmm.find(&impl_id) { - Some(&mis) => { - // If the trait already has an entry in the - // provided_methods_map, we just need to add this - // method to that entry. - debug!("(checking implementation) adding method `%s` \ - to entry for existing trait", - self.crate_context.tcx.sess.str_of( - provided_method_info.method_info.ident)); - mis.push(provided_method_info); - } - None => { - // If the trait doesn't have an entry yet, create one. - debug!("(checking implementation) creating new entry \ - for method `%s`", - self.crate_context.tcx.sess.str_of( - provided_method_info.method_info.ident)); - pmm.insert(impl_id, - @mut ~[provided_method_info]); - } - } + self.crate_context.tcx.provided_method_sources + .insert(new_did, trait_method.def_id); } } - pub fn add_inherent_method(&self, - base_def_id: def_id, - implementation: @Impl) { + pub fn add_inherent_impl(&self, + base_def_id: def_id, + implementation: @Impl) { + let tcx = self.crate_context.tcx; let implementation_list; - match self.crate_context.coherence_info.inherent_methods - .find(&base_def_id) { + match tcx.inherent_impls.find(&base_def_id) { None => { implementation_list = @mut ~[]; - self.crate_context.coherence_info.inherent_methods - .insert(base_def_id, implementation_list); + tcx.inherent_impls.insert(base_def_id, implementation_list); } Some(&existing_implementation_list) => { implementation_list = existing_implementation_list; @@ -435,18 +350,17 @@ impl CoherenceChecker { } implementation_list.push(implementation); - - ty::add_base_impl(self.crate_context.tcx, base_def_id, implementation); } - pub fn add_trait_method(&self, trait_id: def_id, implementation: @Impl) { + pub fn add_trait_impl(&self, + base_def_id: def_id, + implementation: @Impl) { + let tcx = self.crate_context.tcx; let implementation_list; - match self.crate_context.coherence_info.extension_methods - .find(&trait_id) { + match tcx.trait_impls.find(&base_def_id) { None => { implementation_list = @mut ~[]; - self.crate_context.coherence_info.extension_methods - .insert(trait_id, implementation_list); + tcx.trait_impls.insert(base_def_id, implementation_list); } Some(&existing_implementation_list) => { implementation_list = existing_implementation_list; @@ -457,8 +371,7 @@ impl CoherenceChecker { } pub fn check_implementation_coherence(&self) { - let coherence_info = &self.crate_context.coherence_info; - for coherence_info.extension_methods.each_key |&trait_id| { + for self.crate_context.tcx.trait_impls.each_key |&trait_id| { self.check_implementation_coherence_of(trait_id); } } @@ -472,8 +385,6 @@ impl CoherenceChecker { // "We have an impl of trait for type , // and that impl is " - self.add_impl_for_trait(trait_def_id, polytype_a.ty, - implementation_a); do self.iter_impls_of_trait(trait_def_id) |b| { let implementation_b = b; @@ -494,32 +405,8 @@ impl CoherenceChecker { } } - // Adds an impl of trait trait_t for self type self_t; that impl - // is the_impl - pub fn add_impl_for_trait(&self, - trait_t: def_id, - self_t: t, - the_impl: @Impl) { - debug!("Adding impl %? of %? for %s", - the_impl.did, trait_t, - ty_to_str(self.crate_context.tcx, self_t)); - match self.crate_context.tcx.trait_impls.find(&trait_t) { - None => { - let m = @mut HashMap::new(); - m.insert(self_t, the_impl); - self.crate_context.tcx.trait_impls.insert(trait_t, m); - } - Some(&m) => { - m.insert(self_t, the_impl); - } - } - } - pub fn iter_impls_of_trait(&self, trait_def_id: def_id, f: &fn(@Impl)) { - let coherence_info = &self.crate_context.coherence_info; - let extension_methods = &*coherence_info.extension_methods; - - match extension_methods.find(&trait_def_id) { + match self.crate_context.tcx.trait_impls.find(&trait_def_id) { Some(impls) => { for impls.iter().advance |&im| { f(im); @@ -653,13 +540,11 @@ impl CoherenceChecker { // This check doesn't really have anything to do with coherence. It's // here for historical reasons - pub fn please_check_that_trait_methods_are_implemented(&self, - all_methods: - &mut - ~[@MethodInfo], - trait_did: def_id, - trait_ref_span: - span) { + pub fn check_trait_methods_are_implemented( + &self, + all_methods: &mut ~[@Method], + trait_did: def_id, + trait_ref_span: span) { let tcx = self.crate_context.tcx; @@ -668,12 +553,6 @@ impl CoherenceChecker { for uint::range(0, all_methods.len()) |i| { provided_names.insert(all_methods[i].ident); } - // Default methods - let r = ty::provided_trait_methods(tcx, trait_did); - for r.iter().advance |method| { - debug!("inserting provided method %s", method.ident.repr(tcx)); - provided_names.insert(method.ident); - } let r = ty::trait_methods(tcx, trait_did); for r.iter().advance |method| { @@ -726,70 +605,33 @@ impl CoherenceChecker { } } - fn add_provided_methods_to_impl( - &self, - all_methods: &mut ~[@MethodInfo], - trait_did: &ast::def_id, - impl_id: &ast::def_id) { - - - match self.crate_context.tcx - .provided_methods - .find(impl_id) { - None => { - debug!("(creating impl) trait with node_id `%d` \ - has no provided methods", trait_did.node); - /* fall through */ - } - Some(&all_provided_methods) => { - debug!("(creating impl) trait with node_id `%d` \ - has provided methods", trait_did.node); - // Add all provided methods. - for all_provided_methods.iter().advance |provided_method| { - debug!( - "(creating impl) adding provided method \ - `%s` to impl", - provided_method.method_info - .ident.repr(self.crate_context.tcx)); - all_methods.push(provided_method.method_info); - } - } - } - - - } - // Converts an implementation in the AST to an Impl structure. pub fn create_impl_from_item(&self, item: @item) -> @Impl { + let tcx = self.crate_context.tcx; match item.node { item_impl(_, ref trait_refs, _, ref ast_methods) => { let mut methods = ~[]; for ast_methods.iter().advance |ast_method| { - methods.push(method_to_MethodInfo(*ast_method)); + methods.push(ty::method(tcx, local_def(ast_method.id))); } - // Check that we have implementations of every trait method for trait_refs.iter().advance |trait_ref| { - let trait_did = - self.trait_ref_to_trait_def_id(trait_ref); - self.please_check_that_trait_methods_are_implemented( + let ty_trait_ref = ty::node_id_to_trait_ref( + self.crate_context.tcx, + trait_ref.ref_id); + let trait_did = ty_trait_ref.def_id; + + self.instantiate_default_methods(local_def(item.id), + ty_trait_ref, + &mut methods); + + // Check that we have implementations of every trait method + self.check_trait_methods_are_implemented( &mut methods, trait_did, trait_ref.path.span); } - // For each trait that the impl implements, see which - // methods are provided. For each of those methods, - // if a method of that name is not inherent to the - // impl, use the provided definition in the trait. - for trait_refs.iter().advance |trait_ref| { - let trait_did = self.trait_ref_to_trait_def_id(trait_ref); - self.add_provided_methods_to_impl( - &mut methods, - &trait_did, - &local_def(item.id)); - } - return @Impl { did: local_def(item.id), ident: item.ident, @@ -820,12 +662,12 @@ impl CoherenceChecker { pub fn add_external_impl(&self, impls_seen: &mut HashSet, - crate_store: @mut CStore, impl_def_id: def_id) { - let implementation = csearch::get_impl(crate_store, impl_def_id); + let tcx = self.crate_context.tcx; + let implementation = @csearch::get_impl(tcx, impl_def_id); debug!("coherence: adding impl from external crate: %s", - ty::item_path_str(self.crate_context.tcx, implementation.did)); + ty::item_path_str(tcx, implementation.did)); // Make sure we don't visit the same implementation multiple times. if !impls_seen.insert(implementation.did) { @@ -834,9 +676,8 @@ impl CoherenceChecker { } // Good. Continue. - let self_type = lookup_item_type(self.crate_context.tcx, - implementation.did); - let associated_traits = get_impl_trait(self.crate_context.tcx, + let self_type = lookup_item_type(tcx, implementation.did); + let associated_traits = get_impl_trait(tcx, implementation.did); // Do a sanity check to make sure that inherent methods have base @@ -846,35 +687,26 @@ impl CoherenceChecker { dummy_sp(), self_type.ty) { None => { - let session = self.crate_context.tcx.sess; - session.bug(fmt!("no base type for external impl with no \ + tcx.sess.bug(fmt!("no base type for external impl with no \ trait: %s (type %s)!", - session.str_of(implementation.ident), - ty_to_str(self.crate_context.tcx, - self_type.ty))); + tcx.sess.str_of(implementation.ident), + ty_to_str(tcx, self_type.ty))); } Some(_) => {} // Nothing to do. } } // Record all the trait methods. - let mut implementation = @implementation; for associated_traits.iter().advance |trait_ref| { - self.instantiate_default_methods(implementation.did, - *trait_ref); - - // XXX(sully): We could probably avoid this copy if there are no - // default methods. - let mut methods = implementation.methods.clone(); - self.add_provided_methods_to_impl(&mut methods, - &trait_ref.def_id, - &implementation.did); - implementation = @Impl { - methods: methods, - ..*implementation - }; + self.add_trait_impl(trait_ref.def_id, implementation); + } - self.add_trait_method(trait_ref.def_id, implementation); + // For any methods that use a default implementation, add them to + // the map. This is a bit unfortunate. + for implementation.methods.iter().advance |method| { + for method.provided_source.iter().advance |source| { + tcx.provided_method_sources.insert(method.def_id, *source); + } } // Add the implementation to the mapping from implementation to base @@ -887,14 +719,16 @@ impl CoherenceChecker { // inherent methods apply to `impl Type` but not // `impl Trait for Type`: if associated_traits.is_none() { - self.add_inherent_method(base_type_def_id, - implementation); + self.add_inherent_impl(base_type_def_id, + implementation); } self.base_type_def_ids.insert(implementation.did, base_type_def_id); } } + + tcx.impls.insert(implementation.did, implementation); } // Adds implementations and traits from external crates to the coherence @@ -907,9 +741,7 @@ impl CoherenceChecker { for each_path(crate_store, crate_number) |_, def_like, _| { match def_like { dl_impl(def_id) => { - self.add_external_impl(&mut impls_seen, - crate_store, - def_id) + self.add_external_impl(&mut impls_seen, def_id) } dl_def(_) | dl_field => loop, // Skip this. } @@ -922,12 +754,11 @@ impl CoherenceChecker { // pub fn populate_destructor_table(&self) { - let coherence_info = &self.crate_context.coherence_info; let tcx = self.crate_context.tcx; let drop_trait = match tcx.lang_items.drop_trait() { Some(id) => id, None => { return } }; - let impls_opt = coherence_info.extension_methods.find(&drop_trait); + let impls_opt = tcx.trait_impls.find(&drop_trait); let impls; match impls_opt { @@ -940,7 +771,7 @@ impl CoherenceChecker { // We'll error out later. For now, just don't ICE. loop; } - let method_def_id = impl_info.methods[0].did; + let method_def_id = impl_info.methods[0].def_id; let self_type = self.get_self_type_for_implementation(*impl_info); match ty::get(self_type.ty).sty { @@ -1024,7 +855,8 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt, impl_id: ast::def_id, trait_ref: &ty::TraitRef, new_def_id: ast::def_id, - method: &ty::Method) + method: &ty::Method, + provided_source: Option) -> ty::Method { let combined_substs = make_substs_for_receiver_types( @@ -1044,7 +876,9 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt, method.explicit_self, method.vis, - new_def_id + new_def_id, + impl_id, + provided_source ) } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 791774999c2f3..1941317ede5fe 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -376,7 +376,9 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, m_explicit_self.node, // assume public, because this is only invoked on trait methods ast::public, - local_def(*m_id) + local_def(*m_id), + local_def(trait_id), + None ) } } @@ -720,6 +722,7 @@ pub struct ConvertedMethod { } pub fn convert_methods(ccx: &CrateCtxt, + container_id: ast::node_id, ms: &[@ast::method], untransformed_rcvr_ty: ty::t, rcvr_ty_generics: &ty::Generics, @@ -734,7 +737,7 @@ pub fn convert_methods(ccx: &CrateCtxt, ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics, num_rcvr_ty_params); let mty = - @ty_of_method(ccx, *m, rcvr_ty_generics.region_param, + @ty_of_method(ccx, container_id, *m, rcvr_ty_generics.region_param, untransformed_rcvr_ty, rcvr_ast_generics, rcvr_visibility, &m.generics); @@ -760,6 +763,7 @@ pub fn convert_methods(ccx: &CrateCtxt, }).collect(); fn ty_of_method(ccx: &CrateCtxt, + container_id: ast::node_id, m: &ast::method, rp: Option, untransformed_rcvr_ty: ty::t, @@ -790,7 +794,9 @@ pub fn convert_methods(ccx: &CrateCtxt, fty, m.explicit_self.node, method_vis, - local_def(m.id) + local_def(m.id), + local_def(container_id), + None ) } } @@ -849,7 +855,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) { it.vis }; - let cms = convert_methods(ccx, *ms, selfty, + let cms = convert_methods(ccx, it.id, *ms, selfty, &i_ty_generics, generics, parent_visibility); for opt_trait_ref.iter().advance |t| { @@ -867,7 +873,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) { let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id)); let (ty_generics, _) = mk_item_substs(ccx, generics, rp, Some(untransformed_rcvr_ty)); - let _ = convert_methods(ccx, provided_methods, + let _ = convert_methods(ccx, it.id, provided_methods, untransformed_rcvr_ty, &ty_generics, generics, it.vis); diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 5f68f439eba49..bfbebd0a52e9d 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -192,7 +192,6 @@ pub struct CrateCtxt { trait_map: resolve::TraitMap, method_map: method_map, vtable_map: vtable_map, - coherence_info: coherence::CoherenceInfo, tcx: ty::ctxt } @@ -415,7 +414,6 @@ pub fn check_crate(tcx: ty::ctxt, trait_map: trait_map, method_map: @mut HashMap::new(), vtable_map: @mut HashMap::new(), - coherence_info: coherence::CoherenceInfo(), tcx: tcx }; diff --git a/src/test/auxiliary/trait_default_method_xc_aux_2.rs b/src/test/auxiliary/trait_default_method_xc_aux_2.rs new file mode 100644 index 0000000000000..2d4f539f82bbd --- /dev/null +++ b/src/test/auxiliary/trait_default_method_xc_aux_2.rs @@ -0,0 +1,17 @@ +// aux-build:trait_default_method_xc_aux.rs + +extern mod aux(name = "trait_default_method_xc_aux"); +use aux::A; + +pub struct a_struct { x: int } + +impl A for a_struct { + fn f(&self) -> int { 10 } +} + +// This function will need to get inlined, and badness may result. +pub fn welp(x: A) -> A { + let a = a_struct { x: 0 }; + a.g(); + x +} diff --git a/src/test/run-pass/trait-default-method-xc-2.rs b/src/test/run-pass/trait-default-method-xc-2.rs new file mode 100644 index 0000000000000..1dad5d23b8823 --- /dev/null +++ b/src/test/run-pass/trait-default-method-xc-2.rs @@ -0,0 +1,25 @@ +// xfail-fast +// aux-build:trait_default_method_xc_aux.rs +// aux-build:trait_default_method_xc_aux_2.rs + + +extern mod aux(name = "trait_default_method_xc_aux"); +extern mod aux2(name = "trait_default_method_xc_aux_2"); +use aux::A; +use aux2::{a_struct, welp}; + + +fn main () { + + let a = a_struct { x: 0 }; + let b = a_struct { x: 1 }; + + assert_eq!(0i.g(), 10); + assert_eq!(a.g(), 10); + assert_eq!(a.h(), 11); + assert_eq!(b.g(), 10); + assert_eq!(b.h(), 11); + assert_eq!(A::lurr(&a, &b), 21); + + welp(&0); +}