Skip to content

Commit c886629

Browse files
committed
rustc: Implement monomorphic default methods. r=nmatsakis
1 parent 2a1aa9f commit c886629

22 files changed

+638
-300
lines changed

src/rustc/metadata/common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f
124124
tag_table_legacy_boxed_trait = 0x63
125125
}
126126

127+
const tag_item_trait_method_sort: uint = 0x70;
128+
127129
type link_meta = {name: ~str, vers: ~str, extras_hash: ~str};
128130

src/rustc/metadata/csearch.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export get_region_param;
2323
export get_enum_variants;
2424
export get_impls_for_mod;
2525
export get_trait_methods;
26+
export get_provided_trait_methods;
2627
export get_method_names_if_trait;
2728
export get_item_attrs;
2829
export each_path;
@@ -31,6 +32,12 @@ export get_impl_traits;
3132
export get_impl_method;
3233
export get_item_path;
3334
export maybe_get_item_ast, found_ast, found, found_parent, not_found;
35+
export ProvidedTraitMethodInfo;
36+
37+
struct ProvidedTraitMethodInfo {
38+
ty: ty::method,
39+
def_id: ast::def_id
40+
}
3441

3542
fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> ~str {
3643
let cdata = cstore::get_crate_data(cstore, def.crate).data;
@@ -99,6 +106,13 @@ fn get_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> @~[ty::method] {
99106
decoder::get_trait_methods(cstore.intr, cdata, def.node, tcx)
100107
}
101108

109+
fn get_provided_trait_methods(tcx: ty::ctxt, def: ast::def_id) ->
110+
~[ProvidedTraitMethodInfo] {
111+
let cstore = tcx.cstore;
112+
let cdata = cstore::get_crate_data(cstore, def.crate);
113+
decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx)
114+
}
115+
102116
fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id)
103117
-> Option<@DVec<(ast::ident, ast::self_ty_)>> {
104118

src/rustc/metadata/decoder.rs

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use syntax::diagnostic::span_handler;
1919
use common::*;
2020
use syntax::parse::token::ident_interner;
2121
use hash::{Hash, HashUtil};
22+
use csearch::ProvidedTraitMethodInfo;
2223

2324
export class_dtor;
2425
export get_class_fields;
@@ -40,6 +41,7 @@ export get_crate_hash;
4041
export get_crate_vers;
4142
export get_impls_for_mod;
4243
export get_trait_methods;
44+
export get_provided_trait_methods;
4345
export get_method_names_if_trait;
4446
export get_item_attrs;
4547
export get_crate_module_paths;
@@ -164,6 +166,13 @@ fn item_family(item: ebml::Doc) -> Family {
164166
}
165167
}
166168

169+
fn item_method_sort(item: ebml::Doc) -> char {
170+
for ebml::tagged_docs(item, tag_item_trait_method_sort) |doc| {
171+
return str::from_bytes(ebml::doc_data(doc))[0] as char;
172+
}
173+
return 'r';
174+
}
175+
167176
fn item_symbol(item: ebml::Doc) -> ~str {
168177
let sym = ebml::get_doc(item, tag_items_data_item_symbol);
169178
return str::from_bytes(ebml::doc_data(sym));
@@ -701,21 +710,60 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
701710
let bounds = item_ty_param_bounds(mth, tcx, cdata);
702711
let name = item_name(intr, mth);
703712
let ty = doc_type(mth, tcx, cdata);
713+
let def_id = item_def_id(mth, cdata);
704714
let fty = match ty::get(ty).sty {
705715
ty::ty_fn(f) => f,
706716
_ => {
707717
tcx.diag.handler().bug(
708718
~"get_trait_methods: id has non-function type");
709719
} };
710720
let self_ty = get_self_ty(mth);
711-
result.push({ident: name, tps: bounds, fty: fty,
712-
self_ty: self_ty,
713-
vis: ast::public});
721+
result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty,
722+
vis: ast::public, def_id: def_id});
714723
}
715724
debug!("get_trait_methods: }");
716725
@result
717726
}
718727

728+
fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
729+
id: ast::node_id, tcx: ty::ctxt) ->
730+
~[ProvidedTraitMethodInfo] {
731+
let data = cdata.data;
732+
let item = lookup_item(id, data);
733+
let mut result = ~[];
734+
735+
for ebml::tagged_docs(item, tag_item_trait_method) |mth| {
736+
if item_method_sort(mth) != 'p' { loop; }
737+
738+
let did = item_def_id(mth, cdata);
739+
740+
let bounds = item_ty_param_bounds(mth, tcx, cdata);
741+
let name = item_name(intr, mth);
742+
let ty = doc_type(mth, tcx, cdata);
743+
744+
let fty;
745+
match ty::get(ty).sty {
746+
ty::ty_fn(f) => fty = f,
747+
_ => {
748+
tcx.diag.handler().bug(~"get_provided_trait_methods(): id \
749+
has non-function type");
750+
}
751+
}
752+
753+
let self_ty = get_self_ty(mth);
754+
let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty,
755+
vis: ast::public, def_id: did};
756+
let provided_trait_method_info = ProvidedTraitMethodInfo {
757+
ty: ty_method,
758+
def_id: did
759+
};
760+
761+
vec::push(&mut result, move provided_trait_method_info);
762+
}
763+
764+
return move result;
765+
}
766+
719767
// If the item in question is a trait, returns its set of methods and
720768
// their self types. Otherwise, returns none. This overlaps in an
721769
// annoying way with get_trait_methods.

src/rustc/metadata/encoder.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,12 @@ fn encode_self_type(ebml_w: ebml::Serializer, self_type: ast::self_ty_) {
388388
ebml_w.end_tag();
389389
}
390390

391+
fn encode_method_sort(ebml_w: ebml::Serializer, sort: char) {
392+
ebml_w.start_tag(tag_item_trait_method_sort);
393+
ebml_w.writer.write(&[ sort as u8 ]);
394+
ebml_w.end_tag();
395+
}
396+
391397
/* Returns an index of items in this class */
392398
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
393399
id: node_id, path: ast_map::path,
@@ -726,6 +732,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
726732
}
727733
}
728734
item_trait(tps, traits, ms) => {
735+
let provided_methods = dvec::DVec();
736+
729737
add_to_index();
730738
ebml_w.start_tag(tag_items_data_item);
731739
encode_def_id(ebml_w, local_def(item.id));
@@ -746,12 +754,21 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
746754
encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
747755
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
748756
encode_self_type(ebml_w, mty.self_ty);
757+
encode_method_sort(ebml_w, 'r');
749758
ebml_w.end_tag();
750759
}
751760
provided(m) => {
752-
encode_info_for_method(ecx, ebml_w, path,
753-
should_inline(m.attrs), item.id,
754-
m, m.tps);
761+
provided_methods.push(m);
762+
763+
ebml_w.start_tag(tag_item_trait_method);
764+
encode_def_id(ebml_w, local_def(m.id));
765+
encode_name(ecx, ebml_w, mty.ident);
766+
encode_type_param_bounds(ebml_w, ecx, m.tps);
767+
encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
768+
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
769+
encode_self_type(ebml_w, mty.self_ty);
770+
encode_method_sort(ebml_w, 'p');
771+
ebml_w.end_tag();
755772
}
756773
}
757774
i += 1u;
@@ -785,7 +802,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
785802
ebml_w.end_tag();
786803
}
787804

788-
805+
// Finally, output all the provided methods as items.
806+
for provided_methods.each |m| {
807+
index.push({val: m.id, pos: ebml_w.writer.tell()});
808+
encode_info_for_method(ecx, ebml_w, path, true, item.id, *m,
809+
m.tps);
810+
}
789811
}
790812
item_mac(*) => fail ~"item macros unimplemented"
791813
}

src/rustc/middle/resolve.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4680,15 +4680,18 @@ impl Resolver {
46804680
}
46814681
46824682
fn search_for_traits_containing_method(name: ident) -> @DVec<def_id> {
4683+
debug!("(searching for traits containing method) looking for '%s'",
4684+
self.session.str_of(name));
4685+
46834686
let found_traits = @DVec();
46844687
let mut search_module = self.current_module;
46854688
loop {
46864689
// Look for the current trait.
46874690
match copy self.current_trait_refs {
46884691
Some(trait_def_ids) => {
46894692
for trait_def_ids.each |trait_def_id| {
4690-
self.add_trait_info_if_containing_method
4691-
(found_traits, *trait_def_id, name);
4693+
self.add_trait_info_if_containing_method(
4694+
found_traits, *trait_def_id, name);
46924695
}
46934696
}
46944697
None => {
@@ -4702,8 +4705,8 @@ impl Resolver {
47024705
Some(def) => {
47034706
match def.def {
47044707
def_ty(trait_def_id) => {
4705-
self.add_trait_info_if_containing_method
4706-
(found_traits, trait_def_id, name);
4708+
self.add_trait_info_if_containing_method(
4709+
found_traits, trait_def_id, name);
47074710
}
47084711
_ => {
47094712
// Continue.
@@ -4730,8 +4733,8 @@ impl Resolver {
47304733
match def.def {
47314734
def_ty(trait_def_id) => {
47324735
self.
4733-
add_trait_info_if_containing_method
4734-
(found_traits, trait_def_id, name);
4736+
add_trait_info_if_containing_method(
4737+
found_traits, trait_def_id, name);
47354738
}
47364739
_ => {
47374740
// Continue.
@@ -4766,6 +4769,12 @@ impl Resolver {
47664769
trait_def_id: def_id,
47674770
name: ident) {
47684771
4772+
debug!("(adding trait info if containing method) trying trait %d:%d \
4773+
for method '%s'",
4774+
trait_def_id.crate,
4775+
trait_def_id.node,
4776+
self.session.str_of(name));
4777+
47694778
match self.trait_info.find(trait_def_id) {
47704779
Some(trait_info) if trait_info.contains_key(name) => {
47714780
debug!("(adding trait info if containing method) found trait \

0 commit comments

Comments
 (0)