1
Fork 0

rustc: Move ty::impl_traits over to a multiple-traits-per-impl world

This commit is contained in:
Patrick Walton 2012-07-18 16:49:55 -07:00
parent 3c583def25
commit 9d34c706b2
4 changed files with 65 additions and 54 deletions

View file

@ -3263,7 +3263,7 @@ class Resolver {
visitor: ResolveVisitor) {
// Add a type into the def map. This is needed to prevent an ICE in
// ty::impl_trait.
// ty::impl_traits.
// If applicable, create a rib for the type parameters.
let outer_type_parameter_count = (*type_parameters).len();

View file

@ -253,10 +253,12 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t],
vtables: typeck::vtable_res) -> ValueRef {
let _icx = ccx.insn_ctxt(~"impl::make_impl_vtable");
let tcx = ccx.tcx;
// XXX: This should support multiple traits.
let ifce_id = expect(ccx.sess,
ty::ty_to_def_id(option::get(ty::impl_trait(tcx,
impl_id))),
ty::ty_to_def_id(ty::impl_traits(tcx, impl_id)[0]),
|| ~"make_impl_vtable: non-trait-type implemented");
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
make_vtable(ccx, vec::map(*ty::trait_methods(tcx, ifce_id), |im| {
let fty = ty::subst_tps(tcx, substs, ty::mk_fn(tcx, im.fty));

View file

@ -65,7 +65,7 @@ export subst, subst_tps, substs_is_noop, substs_to_str, substs;
export t;
export new_ty_hash;
export enum_variants, substd_enum_variants, enum_is_univariant;
export trait_methods, store_trait_methods, impl_trait;
export trait_methods, store_trait_methods, impl_traits;
export enum_variant_with_id;
export ty_dtor;
export ty_param_bounds_and_ty;
@ -2474,38 +2474,48 @@ fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
result
}
// XXX: Needs to return an array of traits.
fn impl_trait(cx: ctxt, id: ast::def_id) -> option<t> {
fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] {
if id.crate == ast::local_crate {
#debug("(impl_trait) searching for trait impl %?", id);
#debug("(impl_traits) searching for trait impl %?", id);
alt cx.items.find(id.node) {
some(ast_map::node_item(@{
node: ast::item_impl(_, traits, _, _),
_},
_)) if traits.len() >= 1 {
some(node_id_to_type(cx, traits[0].ref_id))
node: ast::item_impl(_, trait_refs, _, _),
_},
_)) {
do vec::map(trait_refs) |trait_ref| {
node_id_to_type(cx, trait_ref.ref_id)
}
}
some(ast_map::node_item(@{node: ast::item_class(*),
_},_)) {
alt cx.def_map.find(id.node) {
some(def_ty(trait_id)) {
// XXX: Doesn't work cross-crate.
#debug("(impl_trait) found trait id %?", trait_id);
some(node_id_to_type(cx, trait_id.node))
#debug("(impl_traits) found trait id %?", trait_id);
~[node_id_to_type(cx, trait_id.node)]
}
some(x) {
cx.sess.bug(#fmt("impl_trait: trait ref is in trait map \
cx.sess.bug(#fmt("impl_traits: trait ref is in trait map \
but is bound to %?", x));
}
none {
none
~[]
}
}
}
_ { none }
_ { ~[] }
}
} else {
csearch::get_impl_trait(cx, id)
// XXX: csearch::get_impl_trait should return a vector.
alt csearch::get_impl_trait(cx, id) {
none {
~[]
}
some(trait_ref) {
~[trait_ref]
}
}
}
}

View file

@ -119,44 +119,41 @@ fn lookup_vtable(fcx: @fn_ctxt, isc: resolve::iscopes, sp: span,
for vec::each(*impls) |im| {
// im = one specific impl
// find the trait that im implements (if any)
let of_ty = alt ty::impl_trait(tcx, im.did) {
some(of_ty) { of_ty }
_ { again; }
};
for vec::each(ty::impl_traits(tcx, im.did)) |of_ty| {
// it must have the same id as the expected one
alt ty::get(of_ty).struct {
ty::ty_trait(id, _) if id != trait_id { again; }
_ { /* ok */ }
}
// it must have the same id as the expected one
alt ty::get(of_ty).struct {
ty::ty_trait(id, _) if id != trait_id { again; }
_ { /* ok */ }
// check whether the type unifies with the type
// that the impl is for, and continue if not
let {substs: substs, ty: for_ty} =
impl_self_ty(fcx, im.did);
let im_bs = ty::lookup_item_type(tcx, im.did).bounds;
alt fcx.mk_subty(ty, for_ty) {
result::err(_) { again; }
result::ok(()) { }
}
// check that desired trait type unifies
#debug("(checking vtable) @2 relating trait ty %s to \
of_ty %s",
fcx.infcx.ty_to_str(trait_ty),
fcx.infcx.ty_to_str(of_ty));
let of_ty = ty::subst(tcx, substs, of_ty);
relate_trait_tys(fcx, sp, trait_ty, of_ty);
// recursively process the bounds
let trait_tps = trait_substs.tps;
let substs_f = fixup_substs(fcx, sp, trait_id, substs);
connect_trait_tps(fcx, sp, substs_f.tps,
trait_tps, im.did);
let subres = lookup_vtables(fcx, isc, sp,
im_bs, substs_f, false);
vec::push(found,
vtable_static(im.did, substs_f.tps, subres));
}
// check whether the type unifies with the type
// that the impl is for, and continue if not
let {substs: substs, ty: for_ty} =
impl_self_ty(fcx, im.did);
let im_bs = ty::lookup_item_type(tcx, im.did).bounds;
alt fcx.mk_subty(ty, for_ty) {
result::err(_) { again; }
result::ok(()) { }
}
// check that desired trait type unifies
#debug("(checking vtable) @2 relating trait ty %s to \
of_ty %s",
fcx.infcx.ty_to_str(trait_ty),
fcx.infcx.ty_to_str(of_ty));
let of_ty = ty::subst(tcx, substs, of_ty);
relate_trait_tys(fcx, sp, trait_ty, of_ty);
// recursively process the bounds
let trait_tps = trait_substs.tps;
let substs_f = fixup_substs(fcx, sp, trait_id, substs);
connect_trait_tps(fcx, sp, substs_f.tps,
trait_tps, im.did);
let subres = lookup_vtables(fcx, isc, sp,
im_bs, substs_f, false);
vec::push(found,
vtable_static(im.did, substs_f.tps, subres));
}
alt found.len() {
@ -195,7 +192,9 @@ fn fixup_ty(fcx: @fn_ctxt, sp: span, ty: ty::t) -> ty::t {
fn connect_trait_tps(fcx: @fn_ctxt, sp: span, impl_tys: ~[ty::t],
trait_tys: ~[ty::t], impl_did: ast::def_id) {
let tcx = fcx.ccx.tcx;
let ity = option::get(ty::impl_trait(tcx, impl_did));
// XXX: This should work for multiple traits.
let ity = ty::impl_traits(tcx, impl_did)[0];
let trait_ty = ty::subst_tps(tcx, impl_tys, ity);
#debug("(connect trait tps) trait type is %?, impl did is %?",
ty::get(trait_ty).struct, impl_did);