Skip to content

Commit 25e6523

Browse files
committed
Check impls methods against the type of their iface.
1 parent 057617c commit 25e6523

File tree

5 files changed

+87
-44
lines changed

5 files changed

+87
-44
lines changed

src/comp/metadata/tydecode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
267267
while peek(st) as char != '[' {
268268
name += str::unsafe_from_byte(next(st));
269269
}
270-
methods += [{ident: name,
270+
methods += [{ident: name, tps: [],
271271
fty: {proto: proto with parse_ty_fn(st, sd)}}];
272272
}
273273
st.pos += 1u;

src/comp/middle/ty.rs

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export substitute_type_params;
103103
export t;
104104
export new_ty_hash;
105105
export tag_variants;
106+
export iface_methods, store_iface_methods;
106107
export tag_variant_with_id;
107108
export ty_param_substs_opt_and_ty;
108109
export ty_param_kinds_and_ty;
@@ -191,7 +192,7 @@ type arg = {mode: mode, ty: t};
191192

192193
type field = {ident: ast::ident, mt: mt};
193194

194-
type method = {ident: ast::ident, fty: fn_ty};
195+
type method = {ident: ast::ident, tps: [ast::kind], fty: fn_ty};
195196

196197
type constr_table = hashmap<ast::node_id, [constr]>;
197198

@@ -215,7 +216,8 @@ type ctxt =
215216
needs_drop_cache: hashmap<t, bool>,
216217
kind_cache: hashmap<t, ast::kind>,
217218
ast_ty_to_ty_cache: hashmap<@ast::ty, option::t<t>>,
218-
tag_var_cache: hashmap<ast::def_id, @[variant_info]>};
219+
tag_var_cache: hashmap<ast::def_id, @[variant_info]>,
220+
iface_method_cache: hashmap<def_id, @[method]>};
219221

220222
type ty_ctxt = ctxt;
221223

@@ -412,7 +414,8 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
412414
kind_cache: new_ty_hash(),
413415
ast_ty_to_ty_cache:
414416
map::mk_hashmap(ast_util::hash_ty, ast_util::eq_ty),
415-
tag_var_cache: new_def_hash()};
417+
tag_var_cache: new_def_hash(),
418+
iface_method_cache: new_def_hash()};
416419
populate_type_store(cx);
417420
ret cx;
418421
}
@@ -752,7 +755,7 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
752755
let new_args = vec::map(m.fty.inputs, {|a|
753756
{mode: a.mode, ty: fold_ty(cx, fld, a.ty)}
754757
});
755-
{ident: m.ident,
758+
{ident: m.ident, tps: m.tps,
756759
fty: {inputs: new_args,
757760
output: fold_ty(cx, fld, m.fty.output)
758761
with m.fty}}
@@ -1961,7 +1964,8 @@ mod unify {
19611964
ures_ok(tfn) {
19621965
alt struct(cx.tcx, tfn) {
19631966
ty_fn(f) {
1964-
result_meths += [{ident: e_meth.ident, fty: f}];
1967+
result_meths += [{ident: e_meth.ident,
1968+
tps: a_meth.tps, fty: f}];
19651969
}
19661970
}
19671971
}
@@ -2479,7 +2483,7 @@ fn same_type(cx: ctxt, a: t, b: t) -> bool {
24792483
}
24802484
}
24812485
fn same_method(cx: ctxt, a: method, b: method) -> bool {
2482-
a.fty.proto == b.fty.proto && a.ident == b.ident &&
2486+
a.tps == b.tps && a.fty.proto == b.fty.proto && a.ident == b.ident &&
24832487
vec::all2(a.fty.inputs, b.fty.inputs,
24842488
{|a, b| a.mode == b.mode && same_type(cx, a.ty, b.ty) }) &&
24852489
same_type(cx, a.fty.output, b.fty.output) &&
@@ -2587,6 +2591,21 @@ fn def_has_ty_params(def: ast::def) -> bool {
25872591
}
25882592
}
25892593

2594+
fn store_iface_methods(cx: ctxt, id: ast::node_id, ms: @[method]) {
2595+
cx.iface_method_cache.insert(ast_util::local_def(id), ms);
2596+
}
2597+
2598+
fn iface_methods(cx: ctxt, id: ast::def_id) -> @[method] {
2599+
alt cx.iface_method_cache.find(id) {
2600+
some(ms) { ret ms; }
2601+
_ {}
2602+
}
2603+
// Local interfaces are supposed to have been added explicitly.
2604+
assert id.crate != ast::local_crate;
2605+
let result = @[]; // FIXME[impl]
2606+
cx.iface_method_cache.insert(id, result);
2607+
result
2608+
}
25902609

25912610
// Tag information
25922611
type variant_info = @{args: [ty::t], ctor_ty: ty::t, id: ast::def_id};
@@ -2600,20 +2619,16 @@ fn tag_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
26002619
@csearch::get_tag_variants(cx, id)
26012620
} else {
26022621
alt cx.items.get(id.node) {
2603-
ast_map::node_item(item) {
2604-
alt item.node {
2605-
ast::item_tag(variants, _) {
2606-
@vec::map(variants, {|variant|
2607-
let ctor_ty = node_id_to_monotype(cx, variant.node.id);
2608-
let arg_tys = if vec::len(variant.node.args) > 0u {
2609-
vec::map(ty_fn_args(cx, ctor_ty), {|a| a.ty})
2610-
} else { [] };
2611-
@{args: arg_tys,
2612-
ctor_ty: ctor_ty,
2613-
id: ast_util::local_def(variant.node.id)}
2614-
})
2615-
}
2616-
}
2622+
ast_map::node_item(@{node: ast::item_tag(variants, _), _}) {
2623+
@vec::map(variants, {|variant|
2624+
let ctor_ty = node_id_to_monotype(cx, variant.node.id);
2625+
let arg_tys = if vec::len(variant.node.args) > 0u {
2626+
vec::map(ty_fn_args(cx, ctor_ty), {|a| a.ty})
2627+
} else { [] };
2628+
@{args: arg_tys,
2629+
ctor_ty: ctor_ty,
2630+
id: ast_util::local_def(variant.node.id)}
2631+
})
26172632
}
26182633
}
26192634
};

src/comp/middle/typeck.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,15 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
422422
tcx.tcache.insert(local_def(it.id), tpt);
423423
ret tpt;
424424
}
425-
ast::item_iface(tps, methods) {
425+
ast::item_iface(tps, ms) {
426426
let t = ty::mk_named(tcx, ty::mk_iface(tcx, local_def(it.id),
427427
mk_ty_params(tcx, tps)),
428428
@it.ident);
429429
let tpt = {kinds: ty_param_kinds(tps), ty: t};
430430
tcx.tcache.insert(local_def(it.id), tpt);
431+
ty::store_iface_methods(tcx, it.id, @vec::map(ms, {|m|
432+
ty_of_ty_method(tcx, m_collect, m)
433+
}));
431434
ret tpt;
432435
}
433436
ast::item_impl(_, _, _, _) | ast::item_mod(_) |
@@ -490,11 +493,13 @@ fn ty_of_native_fn_decl(tcx: ty::ctxt, mode: mode, decl: ast::fn_decl,
490493
ret tpt;
491494
}
492495
fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method {
493-
{ident: m.ident, fty: ty_of_fn_decl(tcx, mode, m.decl)}
496+
{ident: m.ident, tps: vec::map(m.tps, {|tp| tp.kind}),
497+
fty: ty_of_fn_decl(tcx, mode, m.decl)}
494498
}
495499
fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method)
496500
-> ty::method {
497-
{ident: m.ident, fty: ty_of_fn_decl(tcx, mode, m.decl)}
501+
{ident: m.ident, tps: vec::map(m.tps, {|tp| tp.kind}),
502+
fty: ty_of_fn_decl(tcx, mode, m.decl)}
498503
}
499504
fn ty_of_obj(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj,
500505
ty_params: [ast::ty_param]) -> ty::ty_param_kinds_and_ty {
@@ -1493,7 +1498,7 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
14931498
// record projection work on type inferred arguments.
14941499
unify(fcx, expr.span, expected, fty);
14951500

1496-
check_fn1(fcx.ccx, decl, body, expr.id, some(fcx));
1501+
check_fn(fcx.ccx, decl, body, expr.id, some(fcx));
14971502
}
14981503

14991504
fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
@@ -2565,14 +2570,6 @@ fn check_constraints(fcx: @fn_ctxt, cs: [@ast::constr], args: [ast::arg]) {
25652570
}
25662571

25672572
fn check_fn(ccx: @crate_ctxt,
2568-
decl: ast::fn_decl,
2569-
body: ast::blk,
2570-
id: ast::node_id,
2571-
old_fcx: option::t<@fn_ctxt>) {
2572-
check_fn1(ccx, decl, body, id, old_fcx);
2573-
}
2574-
2575-
fn check_fn1(ccx: @crate_ctxt,
25762573
decl: ast::fn_decl,
25772574
body: ast::blk,
25782575
id: ast::node_id,
@@ -2645,10 +2642,41 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
26452642
// Now remove the info from the stack.
26462643
vec::pop(ccx.self_infos);
26472644
}
2648-
ast::item_impl(_, _, ty, ms) {
2645+
ast::item_impl(_, ifce, ty, ms) {
26492646
ccx.self_infos += [self_impl(ast_ty_to_ty(ccx.tcx, m_check, ty))];
2650-
for m in ms { check_method(ccx, m); }
2647+
let my_methods = vec::map(ms, {|m|
2648+
check_method(ccx, m);
2649+
ty_of_method(ccx.tcx, m_check, m)
2650+
});
26512651
vec::pop(ccx.self_infos);
2652+
alt ifce {
2653+
some(ty) {
2654+
alt ty::struct(ccx.tcx, ast_ty_to_ty(ccx.tcx, m_check, ty)) {
2655+
ty::ty_iface(did, tys) {
2656+
for if_m in *ty::iface_methods(ccx.tcx, did) {
2657+
alt vec::find(my_methods, {|m| if_m.ident == m.ident}) {
2658+
some(m) {
2659+
if !ty::same_method(ccx.tcx, m, if_m) {
2660+
ccx.tcx.sess.span_err(
2661+
ty.span, "method " + if_m.ident +
2662+
" has the wrong type");
2663+
}
2664+
}
2665+
none. {
2666+
ccx.tcx.sess.span_err(ty.span, "missing method " +
2667+
if_m.ident);
2668+
}
2669+
}
2670+
}
2671+
}
2672+
_ {
2673+
ccx.tcx.sess.span_err(ty.span, "can only implement interface \
2674+
types");
2675+
}
2676+
}
2677+
}
2678+
_ {}
2679+
}
26522680
}
26532681
_ {/* nothing to do */ }
26542682
}

src/comp/syntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ type ty_field_ = {ident: ident, mt: mt};
309309

310310
type ty_field = spanned<ty_field_>;
311311

312-
type ty_method = {ident: ident, decl: fn_decl, span: span};
312+
type ty_method = {ident: ident, decl: fn_decl, tps: [ty_param], span: span};
313313

314314
tag int_ty { ty_i; ty_char; ty_i8; ty_i16; ty_i32; ty_i64; }
315315

src/comp/syntax/parse/parser.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -285,21 +285,21 @@ fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
285285
constraints: constrs});
286286
}
287287

288-
fn parse_ty_methods(p: parser) -> [ast::ty_method] {
289-
fn parse_method_sig(p: parser) -> ast::ty_method {
288+
fn parse_ty_methods(p: parser, allow_tps: bool) -> [ast::ty_method] {
289+
parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
290290
let flo = p.get_lo_pos();
291291
let proto: ast::proto = parse_method_proto(p);
292292
let ident = parse_value_ident(p);
293+
let tps = allow_tps ? parse_ty_params(p) : [];
293294
let f = parse_ty_fn(proto, p), fhi = p.get_last_hi_pos();
294295
expect(p, token::SEMI);
295296
alt f {
296297
ast::ty_fn(d) {
297-
{ident: ident, decl: d, span: ast_util::mk_sp(flo, fhi)}
298+
{ident: ident, decl: d, tps: tps,
299+
span: ast_util::mk_sp(flo, fhi)}
298300
}
299301
}
300-
}
301-
parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(),
302-
parse_method_sig, p).node
302+
}, p).node
303303
}
304304

305305
fn parse_mt(p: parser) -> ast::mt {
@@ -517,7 +517,7 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
517517
} else if eat_word(p, "sendfn") {
518518
t = parse_ty_fn(ast::proto_send, p);
519519
} else if eat_word(p, "obj") {
520-
t = ast::ty_obj(parse_ty_methods(p));
520+
t = ast::ty_obj(parse_ty_methods(p, false));
521521
} else if p.peek() == token::MOD_SEP || is_ident(p.peek()) {
522522
let path = parse_path(p);
523523
t = ast::ty_path(path, p.get_id());
@@ -1839,7 +1839,7 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
18391839

18401840
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
18411841
let lo = p.get_last_lo_pos(), ident = parse_ident(p),
1842-
tps = parse_ty_params(p), meths = parse_ty_methods(p);
1842+
tps = parse_ty_params(p), meths = parse_ty_methods(p, true);
18431843
ret mk_item(p, lo, p.get_last_hi_pos(), ident,
18441844
ast::item_iface(tps, meths), attrs);
18451845
}

0 commit comments

Comments
 (0)