about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-07-18 16:49:55 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-07-18 16:49:55 -0700
commit9d34c706b2e8d311bea0d25d5c2db340b38ffd42 (patch)
tree77f6e25f9bfcdb49dfb8152c6c03a684f0005064 /src/rustc
parent3c583def25728793f3a20c9ec9d41e5039c04387 (diff)
rustc: Move ty::impl_traits over to a multiple-traits-per-impl world
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/resolve3.rs2
-rw-r--r--src/rustc/middle/trans/impl.rs6
-rw-r--r--src/rustc/middle/ty.rs38
-rw-r--r--src/rustc/middle/typeck/check/vtable.rs71
4 files changed, 64 insertions, 53 deletions
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index b9ca1c7709e..7bbb43a14f9 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 5fc1b204e0e..e27e6d14ec9 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 b750870ff86..381d78bbd6b 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<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]
+            }
+        }
     }
 }
 
diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs
index ad4a7a46c3c..389723c4c80 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; }
-                };
-
-                // 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 */ }
-                }
+                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 */ }
+                    }
 
-                // 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 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);
+                    // 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));
+                    // 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);