Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default methods #3749

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/rustc/metadata/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_table_legacy_boxed_trait = 0x63
}

const tag_item_trait_method_sort: uint = 0x70;

type link_meta = {name: ~str, vers: ~str, extras_hash: ~str};

14 changes: 14 additions & 0 deletions src/rustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export get_region_param;
export get_enum_variants;
export get_impls_for_mod;
export get_trait_methods;
export get_provided_trait_methods;
export get_method_names_if_trait;
export get_item_attrs;
export each_path;
Expand All @@ -31,6 +32,12 @@ export get_impl_traits;
export get_impl_method;
export get_item_path;
export maybe_get_item_ast, found_ast, found, found_parent, not_found;
export ProvidedTraitMethodInfo;

struct ProvidedTraitMethodInfo {
ty: ty::method,
def_id: ast::def_id
}

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

fn get_provided_trait_methods(tcx: ty::ctxt, def: ast::def_id) ->
~[ProvidedTraitMethodInfo] {
let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx)
}

fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id)
-> Option<@DVec<(ast::ident, ast::self_ty_)>> {

Expand Down
54 changes: 51 additions & 3 deletions src/rustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use syntax::diagnostic::span_handler;
use common::*;
use syntax::parse::token::ident_interner;
use hash::{Hash, HashUtil};
use csearch::ProvidedTraitMethodInfo;

export class_dtor;
export get_class_fields;
Expand All @@ -40,6 +41,7 @@ export get_crate_hash;
export get_crate_vers;
export get_impls_for_mod;
export get_trait_methods;
export get_provided_trait_methods;
export get_method_names_if_trait;
export get_item_attrs;
export get_crate_module_paths;
Expand Down Expand Up @@ -166,6 +168,13 @@ fn item_family(item: ebml::Doc) -> Family {
}
}

fn item_method_sort(item: ebml::Doc) -> char {
for ebml::tagged_docs(item, tag_item_trait_method_sort) |doc| {
return str::from_bytes(ebml::doc_data(doc))[0] as char;
}
return 'r';
}

fn item_symbol(item: ebml::Doc) -> ~str {
let sym = ebml::get_doc(item, tag_items_data_item_symbol);
return str::from_bytes(ebml::doc_data(sym));
Expand Down Expand Up @@ -694,21 +703,60 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
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_fn(f) => f,
_ => {
tcx.diag.handler().bug(
~"get_trait_methods: id has non-function type");
} };
let self_ty = get_self_ty(mth);
result.push({ident: name, tps: bounds, fty: fty,
self_ty: self_ty,
vis: ast::public});
result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty,
vis: ast::public, def_id: def_id});
}
debug!("get_trait_methods: }");
@result
}

fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
id: ast::node_id, tcx: ty::ctxt) ->
~[ProvidedTraitMethodInfo] {
let data = cdata.data;
let item = lookup_item(id, data);
let mut result = ~[];

for ebml::tagged_docs(item, tag_item_trait_method) |mth| {
if item_method_sort(mth) != 'p' { loop; }

let did = item_def_id(mth, cdata);

let bounds = item_ty_param_bounds(mth, tcx, cdata);
let name = item_name(intr, mth);
let ty = doc_type(mth, tcx, cdata);

let fty;
match ty::get(ty).sty {
ty::ty_fn(f) => fty = f,
_ => {
tcx.diag.handler().bug(~"get_provided_trait_methods(): id \
has non-function type");
}
}

let self_ty = get_self_ty(mth);
let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty,
vis: ast::public, def_id: did};
let provided_trait_method_info = ProvidedTraitMethodInfo {
ty: ty_method,
def_id: did
};

vec::push(&mut result, move provided_trait_method_info);
}

return move result;
}

// 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.
Expand Down
30 changes: 26 additions & 4 deletions src/rustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,12 @@ fn encode_self_type(ebml_w: ebml::Serializer, self_type: ast::self_ty_) {
ebml_w.end_tag();
}

fn encode_method_sort(ebml_w: ebml::Serializer, sort: char) {
ebml_w.start_tag(tag_item_trait_method_sort);
ebml_w.writer.write(&[ sort as u8 ]);
ebml_w.end_tag();
}

/* Returns an index of items in this class */
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
id: node_id, path: ast_map::path,
Expand Down Expand Up @@ -746,6 +752,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
}
}
item_trait(tps, traits, ms) => {
let provided_methods = dvec::DVec();

add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
Expand All @@ -766,12 +774,21 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
encode_self_type(ebml_w, mty.self_ty);
encode_method_sort(ebml_w, 'r');
ebml_w.end_tag();
}
provided(m) => {
encode_info_for_method(ecx, ebml_w, path,
should_inline(m.attrs), item.id,
m, m.tps);
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.tps);
encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
encode_self_type(ebml_w, mty.self_ty);
encode_method_sort(ebml_w, 'p');
ebml_w.end_tag();
}
}
i += 1u;
Expand Down Expand Up @@ -804,7 +821,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
ebml_w.end_tag();
}


// Finally, output all the provided methods as items.
for provided_methods.each |m| {
index.push({val: m.id, pos: ebml_w.writer.tell()});
encode_info_for_method(ecx, ebml_w, path, true, item.id, *m,
m.tps);
}
}
item_mac(*) => fail ~"item macros unimplemented"
}
Expand Down
21 changes: 15 additions & 6 deletions src/rustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4684,15 +4684,18 @@ impl Resolver {
}

fn search_for_traits_containing_method(name: ident) -> @DVec<def_id> {
debug!("(searching for traits containing method) looking for '%s'",
self.session.str_of(name));

let found_traits = @DVec();
let mut search_module = self.current_module;
loop {
// Look for the current trait.
match copy self.current_trait_refs {
Some(trait_def_ids) => {
for trait_def_ids.each |trait_def_id| {
self.add_trait_info_if_containing_method
(found_traits, *trait_def_id, name);
self.add_trait_info_if_containing_method(
found_traits, *trait_def_id, name);
}
}
None => {
Expand All @@ -4706,8 +4709,8 @@ impl Resolver {
Some(def) => {
match def.def {
def_ty(trait_def_id) => {
self.add_trait_info_if_containing_method
(found_traits, trait_def_id, name);
self.add_trait_info_if_containing_method(
found_traits, trait_def_id, name);
}
_ => {
// Continue.
Expand All @@ -4734,8 +4737,8 @@ impl Resolver {
match def.def {
def_ty(trait_def_id) => {
self.
add_trait_info_if_containing_method
(found_traits, trait_def_id, name);
add_trait_info_if_containing_method(
found_traits, trait_def_id, name);
}
_ => {
// Continue.
Expand Down Expand Up @@ -4770,6 +4773,12 @@ impl Resolver {
trait_def_id: def_id,
name: ident) {

debug!("(adding trait info if containing method) trying trait %d:%d \
for method '%s'",
trait_def_id.crate,
trait_def_id.node,
self.session.str_of(name));

match self.trait_info.find(trait_def_id) {
Some(trait_info) if trait_info.contains_key(name) => {
debug!("(adding trait info if containing method) found trait \
Expand Down
Loading