diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2012-07-23 10:11:10 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2012-07-23 13:24:05 -0700 |
| commit | 674dd14eec29cc28c69c9eff1e22ffd4ddf83f84 (patch) | |
| tree | 481eb7d98a7f627da89332519965ca03ebbb8027 /src | |
| parent | 81f108154a9b419427363484a35423462abdb1b5 (diff) | |
| download | rust-674dd14eec29cc28c69c9eff1e22ffd4ddf83f84.tar.gz rust-674dd14eec29cc28c69c9eff1e22ffd4ddf83f84.zip | |
rustc: Make vtables use the coherence tables
Diffstat (limited to 'src')
| -rw-r--r-- | src/rustc/middle/typeck/check/vtable.rs | 147 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/coherence.rs | 36 |
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 \ |
