From 9d34c706b2e8d311bea0d25d5c2db340b38ffd42 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 18 Jul 2012 16:49:55 -0700 Subject: [PATCH] rustc: Move ty::impl_traits over to a multiple-traits-per-impl world --- src/rustc/middle/resolve3.rs | 2 +- src/rustc/middle/trans/impl.rs | 6 +- src/rustc/middle/ty.rs | 38 ++++++++----- src/rustc/middle/typeck/check/vtable.rs | 73 ++++++++++++------------- 4 files changed, 65 insertions(+), 54 deletions(-) diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs index b9ca1c7709ee..7bbb43a14f90 100644 --- a/src/rustc/middle/resolve3.rs +++ b/src/rustc/middle/resolve3.rs @@ -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(); diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs index 5fc1b204e0ea..e27e6d14ec94 100644 --- a/src/rustc/middle/trans/impl.rs +++ b/src/rustc/middle/trans/impl.rs @@ -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)); diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index b750870ff868..381d78bbd6bb 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -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 { +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] + } + } } } diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs index ad4a7a46c3c3..389723c4c809 100644 --- a/src/rustc/middle/typeck/check/vtable.rs +++ b/src/rustc/middle/typeck/check/vtable.rs @@ -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);