about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-07-23 10:11:10 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-07-23 13:24:05 -0700
commit674dd14eec29cc28c69c9eff1e22ffd4ddf83f84 (patch)
tree481eb7d98a7f627da89332519965ca03ebbb8027 /src/rustc
parent81f108154a9b419427363484a35423462abdb1b5 (diff)
downloadrust-674dd14eec29cc28c69c9eff1e22ffd4ddf83f84.tar.gz
rust-674dd14eec29cc28c69c9eff1e22ffd4ddf83f84.zip
rustc: Make vtables use the coherence tables
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/typeck/check/vtable.rs147
-rw-r--r--src/rustc/middle/typeck/coherence.rs36
2 files changed, 107 insertions, 76 deletions
diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs
index b9fd12becb6..51a412be718 100644
--- a/src/rustc/middle/typeck/check/vtable.rs
+++ b/src/rustc/middle/typeck/check/vtable.rs
@@ -1,6 +1,7 @@
 import check::{fn_ctxt, impl_self_ty, methods};
 import infer::{resolve_type, resolve_all, force_all, fixup_err_to_str};
 import ast_util::new_def_hash;
+import dvec::extensions;
 
 fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
     vec::any(tps, |bs| {
@@ -10,7 +11,7 @@ fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
     })
 }
 
-fn lookup_vtables(fcx: @fn_ctxt, isc: resolve3::ImplScopes, sp: span,
+fn lookup_vtables(fcx: @fn_ctxt, sp: span,
                   bounds: @~[ty::param_bounds], substs: ty::substs,
                   allow_unsafe: bool) -> vtable_res {
     let tcx = fcx.ccx.tcx;
@@ -20,8 +21,8 @@ fn lookup_vtables(fcx: @fn_ctxt, isc: resolve3::ImplScopes, sp: span,
             alt bound {
               ty::bound_trait(i_ty) {
                 let i_ty = ty::subst(tcx, substs, i_ty);
-                vec::push(result, lookup_vtable(fcx, isc, sp, ty, i_ty,
-                                         allow_unsafe));
+                vec::push(result, lookup_vtable(fcx, sp, ty, i_ty,
+                                                allow_unsafe));
               }
               _ {}
             }
@@ -50,12 +51,10 @@ fn relate_trait_tys(fcx: @fn_ctxt, sp: span,
 /*
 Look up the vtable to use when treating an item of type <t>
 as if it has type <trait_ty>
-
-XXX: This doesn't use the coherence tables yet.
 */
-fn lookup_vtable(fcx: @fn_ctxt, isc: resolve3::ImplScopes, sp: span,
-                 ty: ty::t, trait_ty: ty::t, allow_unsafe: bool)
-    -> vtable_origin {
+fn lookup_vtable(fcx: @fn_ctxt, sp: span, ty: ty::t, trait_ty: ty::t,
+                 allow_unsafe: bool)
+              -> vtable_origin {
 
     #debug["lookup_vtable(ty=%s, trait_ty=%s)",
            fcx.infcx.ty_to_str(ty), fcx.infcx.ty_to_str(trait_ty)];
@@ -119,64 +118,72 @@ fn lookup_vtable(fcx: @fn_ctxt, isc: resolve3::ImplScopes, sp: span,
 
         let mut impls_seen = new_def_hash();
 
-        for list::each(isc) |impls| {
-            /* For each impl in scope... */
-            for vec::each(*impls) |im| {
-                // im = one specific impl
+        alt fcx.ccx.coherence_info.extension_methods.find(trait_id) {
+            none {
+                // Nothing found. Continue.
+            }
+            some(implementations) {
+                for uint::range(0, implementations.len()) |i| {
+                    let im = implementations[i];
 
-                // First, ensure that we haven't processed this impl yet.
-                if impls_seen.contains_key(im.did) {
-                    again;
-                }
-                impls_seen.insert(im.did, ());
+                    // im = one specific impl
 
-                // find the trait that im implements (if any)
-                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 */ }
+                    // First, ensure that we haven't processed this impl yet.
+                    if impls_seen.contains_key(im.did) {
+                        again;
                     }
+                    impls_seen.insert(im.did, ());
 
-                    // 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(()) { }
-                    }
+                    // find the trait that im implements (if any)
+                    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 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, sp, im_bs, substs_f,
+                                                    false);
+                        vec::push(found,
+                                  vtable_static(im.did, substs_f.tps,
+                                                subres));
+                    }
                 }
             }
+        }
 
-            alt found.len() {
-              0u { /* fallthrough */ }
-              1u { ret found[0]; }
-              _ {
-                fcx.ccx.tcx.sess.span_err(
-                    sp, ~"multiple applicable methods in scope");
-                ret found[0];
-              }
-            }
+        alt found.len() {
+          0u { /* fallthrough */ }
+          1u { ret found[0]; }
+          _ {
+            fcx.ccx.tcx.sess.span_err(
+                sp, ~"multiple applicable methods in scope");
+            ret found[0];
+          }
         }
       }
     }
@@ -227,10 +234,11 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
             let did = ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id));
             let item_ty = ty::lookup_item_type(cx.tcx, did);
             if has_trait_bounds(*item_ty.bounds) {
-                let impls = cx.impl_map.get(ex.id);
-                cx.vtable_map.insert(ex.id, lookup_vtables(
-                    fcx, impls, ex.span,
-                    item_ty.bounds, substs, false));
+                cx.vtable_map.insert(ex.id, lookup_vtables(fcx,
+                                                           ex.span,
+                                                           item_ty.bounds,
+                                                           substs,
+                                                           false));
             }
           }
           _ {}
@@ -249,9 +257,11 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
                   _ { ex.callee_id }
                 };
                 let substs = fcx.node_ty_substs(callee_id);
-                let iscs = cx.impl_map.get(ex.id);
-                cx.vtable_map.insert(callee_id, lookup_vtables(
-                    fcx, iscs, ex.span, bounds, substs, false));
+                cx.vtable_map.insert(callee_id, lookup_vtables(fcx,
+                                                               ex.span,
+                                                               bounds,
+                                                               substs,
+                                                               false));
             }
           }
           _ {}
@@ -261,17 +271,12 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
         let target_ty = fcx.expr_ty(ex);
         alt ty::get(target_ty).struct {
           ty::ty_trait(*) {
-            /* Casting to an interface type.
-            Look up all impls for the cast expr...
-            */
-            let impls = cx.impl_map.get(ex.id);
             /*
             Look up vtables for the type we're casting to,
             passing in the source and target type
             */
-            let vtable = lookup_vtable(fcx, impls, ex.span,
-                                       fcx.expr_ty(src), target_ty,
-                                       true);
+            let vtable = lookup_vtable(fcx, ex.span, fcx.expr_ty(src),
+                                       target_ty, true);
             /*
             Map this expression to that vtable (that is: "ex has
             vtable <vtable>")
diff --git a/src/rustc/middle/typeck/coherence.rs b/src/rustc/middle/typeck/coherence.rs
index 05bd7b7fac8..005f87e601b 100644
--- a/src/rustc/middle/typeck/coherence.rs
+++ b/src/rustc/middle/typeck/coherence.rs
@@ -17,10 +17,10 @@ import middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box};
 import middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_is_var};
 import middle::typeck::infer::{infer_ctxt, mk_subty};
 import middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
-import syntax::ast::{crate, def_id, def_mod, item, item_class, item_const};
-import syntax::ast::{item_enum, item_fn, item_foreign_mod, item_impl};
-import syntax::ast::{item_mac, item_mod, item_trait, item_ty, local_crate};
-import syntax::ast::{method, node_id};
+import syntax::ast::{class_method, crate, def_id, def_mod, instance_var};
+import syntax::ast::{item, item_class, item_const, item_enum, item_fn};
+import syntax::ast::{item_foreign_mod, item_impl, item_mac, item_mod};
+import syntax::ast::{item_trait, item_ty, local_crate, method, node_id};
 import syntax::ast::{trait_ref};
 import syntax::ast_map::node_item;
 import syntax::ast_util::{def_id_of_def, dummy_sp, new_def_hash};
@@ -161,7 +161,10 @@ class CoherenceChecker {
                 #debug("(checking coherence) item '%s'", *item.ident);
 
                 alt item.node {
-                    item_impl(_, associated_traits, self_type, _) {
+                    item_impl(_, associated_traits, _, _) {
+                        self.check_implementation(item, associated_traits);
+                    }
+                    item_class(_, associated_traits, _, _, _) {
                         self.check_implementation(item, associated_traits);
                     }
                     _ {
@@ -499,6 +502,29 @@ class CoherenceChecker {
                     methods: methods
                 };
             }
+            item_class(ty_params, _, class_members, _, _) {
+                let mut methods = ~[];
+                for class_members.each |class_member| {
+                    alt class_member.node {
+                        instance_var(*) {
+                            // Nothing to do.
+                        }
+                        class_method(ast_method) {
+                            push(methods, @{
+                                did: local_def(ast_method.id),
+                                n_tps: ast_method.tps.len(),
+                                ident: ast_method.ident
+                            });
+                        }
+                    }
+                }
+
+                ret @{
+                    did: local_def(item.id),
+                    ident: item.ident,
+                    methods: methods
+                };
+            }
             _ {
                 self.crate_context.tcx.sess.span_bug(item.span,
                                                      ~"can't convert a \