Skip to content

Implement cross-crate static methods on anonymous trait implementations #3789

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

Closed
wants to merge 2 commits 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
7 changes: 7 additions & 0 deletions src/rustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export get_enum_variants;
export get_impls_for_mod;
export get_trait_methods;
export get_provided_trait_methods;
export get_supertraits;
export get_method_names_if_trait;
export get_type_name_if_impl;
export get_static_methods_if_impl;
Expand Down Expand Up @@ -122,6 +123,12 @@ fn get_provided_trait_methods(tcx: ty::ctxt, def: ast::def_id) ->
decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx)
}

fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] {
let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_supertraits(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
11 changes: 11 additions & 0 deletions src/rustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export get_crate_vers;
export get_impls_for_mod;
export get_trait_methods;
export get_provided_trait_methods;
export get_supertraits;
export get_method_names_if_trait;
export get_type_name_if_impl;
export get_item_attrs;
Expand Down Expand Up @@ -771,6 +772,16 @@ fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
return move result;
}

/// Returns the supertraits of the given trait.
fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::t] {
let results = dvec::DVec();
let item_doc = lookup_item(id, cdata.data);
for ebml::tagged_docs(item_doc, tag_impl_trait) |trait_doc| {
results.push(doc_type(trait_doc, tcx, cdata));
}
return dvec::unwrap(move 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.
Expand Down
56 changes: 54 additions & 2 deletions src/rustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use syntax::print::pprust::*;
use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};

export ProvidedMethodSource;
export InstantiatedTraitRef;
export TyVid, IntVid, FnVid, RegionVid, vid;
export br_hashmap;
export is_instantiable;
Expand Down Expand Up @@ -66,13 +67,15 @@ export sequence_element_type;
export stmt_node_id;
export sty;
export subst, subst_tps, substs_is_noop, substs_to_str, substs;
export subst_substs;
export t;
export new_ty_hash;
export enum_variants, substd_enum_variants, enum_is_univariant;
export trait_methods, store_trait_methods, impl_traits;
export enum_variant_with_id;
export ty_dtor;
export ty_param_bounds_and_ty;
export ty_param_substs_and_ty;
export ty_bool, mk_bool, type_is_bool;
export ty_bot, mk_bot, type_is_bot;
export ty_box, mk_box, mk_imm_box, type_is_box, type_is_boxed;
Expand Down Expand Up @@ -191,6 +194,7 @@ export region_variance, rv_covariant, rv_invariant, rv_contravariant;
export opt_region_variance;
export determine_inherited_purity;
export provided_trait_methods;
export trait_supertraits;
export AutoAdjustment;
export AutoRef, AutoRefKind, AutoSlice, AutoPtr;

Expand Down Expand Up @@ -321,6 +325,11 @@ struct ProvidedMethodSource {
impl_id: ast::def_id
}

struct InstantiatedTraitRef {
def_id: ast::def_id,
tpt: ty_param_substs_and_ty
}

type ctxt =
@{diag: syntax::diagnostic::span_handler,
interner: HashMap<intern_key, t_box>,
Expand Down Expand Up @@ -364,7 +373,8 @@ type ctxt =
normalized_cache: HashMap<t, t>,
lang_items: middle::lang_items::LanguageItems,
legacy_boxed_traits: HashMap<node_id, ()>,
provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>};
provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>};

enum tbox_flag {
has_params = 1,
Expand Down Expand Up @@ -819,6 +829,8 @@ type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
region_param: Option<region_variance>,
ty: t};

type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t};

type type_cache = HashMap<ast::def_id, ty_param_bounds_and_ty>;

type constness_cache = HashMap<ast::def_id, const_eval::constness>;
Expand Down Expand Up @@ -888,7 +900,8 @@ fn mk_ctxt(s: session::Session,
normalized_cache: new_ty_hash(),
lang_items: move lang_items,
legacy_boxed_traits: HashMap(),
provided_method_sources: HashMap()}
provided_method_sources: HashMap(),
supertraits: HashMap()}
}


Expand Down Expand Up @@ -1486,6 +1499,16 @@ fn subst(cx: ctxt,
}
}

// Performs substitutions on a set of substitutions (result = super(sub)) to
// yield a new set of substitutions. This is used in trait inheritance.
fn subst_substs(cx: ctxt, super: &substs, sub: &substs) -> substs {
{
self_r: super.self_r,
self_ty: super.self_ty.map(|typ| subst(cx, sub, *typ)),
tps: super.tps.map(|typ| subst(cx, sub, *typ))
}
}

// Type utilities

fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
Expand Down Expand Up @@ -3365,6 +3388,35 @@ fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
}
}

fn trait_supertraits(cx: ctxt, id: ast::def_id) -> @~[InstantiatedTraitRef] {
// Check the cache.
match cx.supertraits.find(id) {
Some(instantiated_trait_info) => { return instantiated_trait_info; }
None => {} // Continue.
}

// Not in the cache. It had better be in the metadata, which means it
// shouldn't be local.
assert !is_local(id);

// Get the supertraits out of the metadata and create the
// InstantiatedTraitRef for each.
let result = dvec::DVec();
for csearch::get_supertraits(cx, id).each |trait_type| {
match get(*trait_type).sty {
ty_trait(def_id, substs, _) => {
result.push(InstantiatedTraitRef {
def_id: def_id,
tpt: { substs: substs, ty: *trait_type }
});
}
_ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
}
}

// Unwrap and return the result.
return @dvec::unwrap(move result);
}

fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
match cx.trait_method_cache.find(id) {
Expand Down
4 changes: 1 addition & 3 deletions src/rustc/middle/typeck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use syntax::codemap::span;
use pat_util::{pat_is_variant, pat_id_map, PatIdMap};
use middle::ty;
use middle::ty::{arg, field, node_type_table, mk_nil, ty_param_bounds_and_ty};
use middle::ty::{vstore_uniq};
use middle::ty::{ty_param_substs_and_ty, vstore_uniq};
use std::smallintmap;
use std::map;
use std::map::HashMap;
Expand Down Expand Up @@ -174,8 +174,6 @@ impl vtable_origin {

type vtable_map = HashMap<ast::node_id, vtable_res>;

type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t};

type crate_ctxt_ = {// A mapping from method call sites to traits that have
// that method.
trait_map: resolve::TraitMap,
Expand Down
Loading