Skip to content

Commit 674dd14

Browse files
committed
rustc: Make vtables use the coherence tables
1 parent 81f1081 commit 674dd14

File tree

2 files changed

+107
-76
lines changed

2 files changed

+107
-76
lines changed

src/rustc/middle/typeck/check/vtable.rs

Lines changed: 76 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import check::{fn_ctxt, impl_self_ty, methods};
22
import infer::{resolve_type, resolve_all, force_all, fixup_err_to_str};
33
import ast_util::new_def_hash;
4+
import dvec::extensions;
45

56
fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
67
vec::any(tps, |bs| {
@@ -10,7 +11,7 @@ fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
1011
})
1112
}
1213

13-
fn lookup_vtables(fcx: @fn_ctxt, isc: resolve3::ImplScopes, sp: span,
14+
fn lookup_vtables(fcx: @fn_ctxt, sp: span,
1415
bounds: @~[ty::param_bounds], substs: ty::substs,
1516
allow_unsafe: bool) -> vtable_res {
1617
let tcx = fcx.ccx.tcx;
@@ -20,8 +21,8 @@ fn lookup_vtables(fcx: @fn_ctxt, isc: resolve3::ImplScopes, sp: span,
2021
alt bound {
2122
ty::bound_trait(i_ty) {
2223
let i_ty = ty::subst(tcx, substs, i_ty);
23-
vec::push(result, lookup_vtable(fcx, isc, sp, ty, i_ty,
24-
allow_unsafe));
24+
vec::push(result, lookup_vtable(fcx, sp, ty, i_ty,
25+
allow_unsafe));
2526
}
2627
_ {}
2728
}
@@ -50,12 +51,10 @@ fn relate_trait_tys(fcx: @fn_ctxt, sp: span,
5051
/*
5152
Look up the vtable to use when treating an item of type <t>
5253
as if it has type <trait_ty>
53-
54-
XXX: This doesn't use the coherence tables yet.
5554
*/
56-
fn lookup_vtable(fcx: @fn_ctxt, isc: resolve3::ImplScopes, sp: span,
57-
ty: ty::t, trait_ty: ty::t, allow_unsafe: bool)
58-
-> vtable_origin {
55+
fn lookup_vtable(fcx: @fn_ctxt, sp: span, ty: ty::t, trait_ty: ty::t,
56+
allow_unsafe: bool)
57+
-> vtable_origin {
5958

6059
#debug["lookup_vtable(ty=%s, trait_ty=%s)",
6160
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,
119118

120119
let mut impls_seen = new_def_hash();
121120

122-
for list::each(isc) |impls| {
123-
/* For each impl in scope... */
124-
for vec::each(*impls) |im| {
125-
// im = one specific impl
121+
alt fcx.ccx.coherence_info.extension_methods.find(trait_id) {
122+
none {
123+
// Nothing found. Continue.
124+
}
125+
some(implementations) {
126+
for uint::range(0, implementations.len()) |i| {
127+
let im = implementations[i];
126128

127-
// First, ensure that we haven't processed this impl yet.
128-
if impls_seen.contains_key(im.did) {
129-
again;
130-
}
131-
impls_seen.insert(im.did, ());
129+
// im = one specific impl
132130

133-
// find the trait that im implements (if any)
134-
for vec::each(ty::impl_traits(tcx, im.did)) |of_ty| {
135-
// it must have the same id as the expected one
136-
alt ty::get(of_ty).struct {
137-
ty::ty_trait(id, _) if id != trait_id { again; }
138-
_ { /* ok */ }
131+
// First, ensure that we haven't processed this impl yet.
132+
if impls_seen.contains_key(im.did) {
133+
again;
139134
}
135+
impls_seen.insert(im.did, ());
140136

141-
// check whether the type unifies with the type
142-
// that the impl is for, and continue if not
143-
let {substs: substs, ty: for_ty} =
144-
impl_self_ty(fcx, im.did);
145-
let im_bs = ty::lookup_item_type(tcx, im.did).bounds;
146-
alt fcx.mk_subty(ty, for_ty) {
147-
result::err(_) { again; }
148-
result::ok(()) { }
149-
}
137+
// find the trait that im implements (if any)
138+
for vec::each(ty::impl_traits(tcx, im.did)) |of_ty| {
139+
// it must have the same id as the expected one
140+
alt ty::get(of_ty).struct {
141+
ty::ty_trait(id, _) if id != trait_id { again; }
142+
_ { /* ok */ }
143+
}
144+
145+
// check whether the type unifies with the type
146+
// that the impl is for, and continue if not
147+
let {substs: substs, ty: for_ty} =
148+
impl_self_ty(fcx, im.did);
149+
let im_bs = ty::lookup_item_type(tcx, im.did).bounds;
150+
alt fcx.mk_subty(ty, for_ty) {
151+
result::err(_) { again; }
152+
result::ok(()) { }
153+
}
150154

151-
// check that desired trait type unifies
152-
#debug("(checking vtable) @2 relating trait ty %s to \
153-
of_ty %s",
154-
fcx.infcx.ty_to_str(trait_ty),
155-
fcx.infcx.ty_to_str(of_ty));
156-
let of_ty = ty::subst(tcx, substs, of_ty);
157-
relate_trait_tys(fcx, sp, trait_ty, of_ty);
155+
// check that desired trait type unifies
156+
#debug("(checking vtable) @2 relating trait ty %s to \
157+
of_ty %s",
158+
fcx.infcx.ty_to_str(trait_ty),
159+
fcx.infcx.ty_to_str(of_ty));
160+
let of_ty = ty::subst(tcx, substs, of_ty);
161+
relate_trait_tys(fcx, sp, trait_ty, of_ty);
158162

159-
// recursively process the bounds
160-
let trait_tps = trait_substs.tps;
161-
let substs_f = fixup_substs(fcx, sp, trait_id, substs);
162-
connect_trait_tps(fcx, sp, substs_f.tps,
163-
trait_tps, im.did);
164-
let subres = lookup_vtables(fcx, isc, sp,
165-
im_bs, substs_f, false);
166-
vec::push(found,
167-
vtable_static(im.did, substs_f.tps, subres));
163+
// recursively process the bounds
164+
let trait_tps = trait_substs.tps;
165+
let substs_f = fixup_substs(fcx, sp, trait_id,
166+
substs);
167+
connect_trait_tps(fcx, sp, substs_f.tps,
168+
trait_tps, im.did);
169+
let subres = lookup_vtables(fcx, sp, im_bs, substs_f,
170+
false);
171+
vec::push(found,
172+
vtable_static(im.did, substs_f.tps,
173+
subres));
174+
}
168175
}
169176
}
177+
}
170178

171-
alt found.len() {
172-
0u { /* fallthrough */ }
173-
1u { ret found[0]; }
174-
_ {
175-
fcx.ccx.tcx.sess.span_err(
176-
sp, ~"multiple applicable methods in scope");
177-
ret found[0];
178-
}
179-
}
179+
alt found.len() {
180+
0u { /* fallthrough */ }
181+
1u { ret found[0]; }
182+
_ {
183+
fcx.ccx.tcx.sess.span_err(
184+
sp, ~"multiple applicable methods in scope");
185+
ret found[0];
186+
}
180187
}
181188
}
182189
}
@@ -227,10 +234,11 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
227234
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id));
228235
let item_ty = ty::lookup_item_type(cx.tcx, did);
229236
if has_trait_bounds(*item_ty.bounds) {
230-
let impls = cx.impl_map.get(ex.id);
231-
cx.vtable_map.insert(ex.id, lookup_vtables(
232-
fcx, impls, ex.span,
233-
item_ty.bounds, substs, false));
237+
cx.vtable_map.insert(ex.id, lookup_vtables(fcx,
238+
ex.span,
239+
item_ty.bounds,
240+
substs,
241+
false));
234242
}
235243
}
236244
_ {}
@@ -249,9 +257,11 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
249257
_ { ex.callee_id }
250258
};
251259
let substs = fcx.node_ty_substs(callee_id);
252-
let iscs = cx.impl_map.get(ex.id);
253-
cx.vtable_map.insert(callee_id, lookup_vtables(
254-
fcx, iscs, ex.span, bounds, substs, false));
260+
cx.vtable_map.insert(callee_id, lookup_vtables(fcx,
261+
ex.span,
262+
bounds,
263+
substs,
264+
false));
255265
}
256266
}
257267
_ {}
@@ -261,17 +271,12 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) {
261271
let target_ty = fcx.expr_ty(ex);
262272
alt ty::get(target_ty).struct {
263273
ty::ty_trait(*) {
264-
/* Casting to an interface type.
265-
Look up all impls for the cast expr...
266-
*/
267-
let impls = cx.impl_map.get(ex.id);
268274
/*
269275
Look up vtables for the type we're casting to,
270276
passing in the source and target type
271277
*/
272-
let vtable = lookup_vtable(fcx, impls, ex.span,
273-
fcx.expr_ty(src), target_ty,
274-
true);
278+
let vtable = lookup_vtable(fcx, ex.span, fcx.expr_ty(src),
279+
target_ty, true);
275280
/*
276281
Map this expression to that vtable (that is: "ex has
277282
vtable <vtable>")

src/rustc/middle/typeck/coherence.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ import middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box};
1717
import middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_is_var};
1818
import middle::typeck::infer::{infer_ctxt, mk_subty};
1919
import middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
20-
import syntax::ast::{crate, def_id, def_mod, item, item_class, item_const};
21-
import syntax::ast::{item_enum, item_fn, item_foreign_mod, item_impl};
22-
import syntax::ast::{item_mac, item_mod, item_trait, item_ty, local_crate};
23-
import syntax::ast::{method, node_id};
20+
import syntax::ast::{class_method, crate, def_id, def_mod, instance_var};
21+
import syntax::ast::{item, item_class, item_const, item_enum, item_fn};
22+
import syntax::ast::{item_foreign_mod, item_impl, item_mac, item_mod};
23+
import syntax::ast::{item_trait, item_ty, local_crate, method, node_id};
2424
import syntax::ast::{trait_ref};
2525
import syntax::ast_map::node_item;
2626
import syntax::ast_util::{def_id_of_def, dummy_sp, new_def_hash};
@@ -161,7 +161,10 @@ class CoherenceChecker {
161161
#debug("(checking coherence) item '%s'", *item.ident);
162162

163163
alt item.node {
164-
item_impl(_, associated_traits, self_type, _) {
164+
item_impl(_, associated_traits, _, _) {
165+
self.check_implementation(item, associated_traits);
166+
}
167+
item_class(_, associated_traits, _, _, _) {
165168
self.check_implementation(item, associated_traits);
166169
}
167170
_ {
@@ -499,6 +502,29 @@ class CoherenceChecker {
499502
methods: methods
500503
};
501504
}
505+
item_class(ty_params, _, class_members, _, _) {
506+
let mut methods = ~[];
507+
for class_members.each |class_member| {
508+
alt class_member.node {
509+
instance_var(*) {
510+
// Nothing to do.
511+
}
512+
class_method(ast_method) {
513+
push(methods, @{
514+
did: local_def(ast_method.id),
515+
n_tps: ast_method.tps.len(),
516+
ident: ast_method.ident
517+
});
518+
}
519+
}
520+
}
521+
522+
ret @{
523+
did: local_def(item.id),
524+
ident: item.ident,
525+
methods: methods
526+
};
527+
}
502528
_ {
503529
self.crate_context.tcx.sess.span_bug(item.span,
504530
~"can't convert a \

0 commit comments

Comments
 (0)