while peek(st) as char != '[' {
name += str::unsafe_from_byte(next(st));
}
- methods += [{ident: name,
+ methods += [{ident: name, tps: [],
fty: {proto: proto with parse_ty_fn(st, sd)}}];
}
st.pos += 1u;
export t;
export new_ty_hash;
export tag_variants;
+export iface_methods, store_iface_methods;
export tag_variant_with_id;
export ty_param_substs_opt_and_ty;
export ty_param_kinds_and_ty;
type field = {ident: ast::ident, mt: mt};
-type method = {ident: ast::ident, fty: fn_ty};
+type method = {ident: ast::ident, tps: [ast::kind], fty: fn_ty};
type constr_table = hashmap<ast::node_id, [constr]>;
needs_drop_cache: hashmap<t, bool>,
kind_cache: hashmap<t, ast::kind>,
ast_ty_to_ty_cache: hashmap<@ast::ty, option::t<t>>,
- tag_var_cache: hashmap<ast::def_id, @[variant_info]>};
+ tag_var_cache: hashmap<ast::def_id, @[variant_info]>,
+ iface_method_cache: hashmap<def_id, @[method]>};
type ty_ctxt = ctxt;
kind_cache: new_ty_hash(),
ast_ty_to_ty_cache:
map::mk_hashmap(ast_util::hash_ty, ast_util::eq_ty),
- tag_var_cache: new_def_hash()};
+ tag_var_cache: new_def_hash(),
+ iface_method_cache: new_def_hash()};
populate_type_store(cx);
ret cx;
}
let new_args = vec::map(m.fty.inputs, {|a|
{mode: a.mode, ty: fold_ty(cx, fld, a.ty)}
});
- {ident: m.ident,
+ {ident: m.ident, tps: m.tps,
fty: {inputs: new_args,
output: fold_ty(cx, fld, m.fty.output)
with m.fty}}
ures_ok(tfn) {
alt struct(cx.tcx, tfn) {
ty_fn(f) {
- result_meths += [{ident: e_meth.ident, fty: f}];
+ result_meths += [{ident: e_meth.ident,
+ tps: a_meth.tps, fty: f}];
}
}
}
}
}
fn same_method(cx: ctxt, a: method, b: method) -> bool {
- a.fty.proto == b.fty.proto && a.ident == b.ident &&
+ a.tps == b.tps && a.fty.proto == b.fty.proto && a.ident == b.ident &&
vec::all2(a.fty.inputs, b.fty.inputs,
{|a, b| a.mode == b.mode && same_type(cx, a.ty, b.ty) }) &&
same_type(cx, a.fty.output, b.fty.output) &&
}
}
+fn store_iface_methods(cx: ctxt, id: ast::node_id, ms: @[method]) {
+ cx.iface_method_cache.insert(ast_util::local_def(id), ms);
+}
+
+fn iface_methods(cx: ctxt, id: ast::def_id) -> @[method] {
+ alt cx.iface_method_cache.find(id) {
+ some(ms) { ret ms; }
+ _ {}
+ }
+ // Local interfaces are supposed to have been added explicitly.
+ assert id.crate != ast::local_crate;
+ let result = @[]; // FIXME[impl]
+ cx.iface_method_cache.insert(id, result);
+ result
+}
// Tag information
type variant_info = @{args: [ty::t], ctor_ty: ty::t, id: ast::def_id};
@csearch::get_tag_variants(cx, id)
} else {
alt cx.items.get(id.node) {
- ast_map::node_item(item) {
- alt item.node {
- ast::item_tag(variants, _) {
- @vec::map(variants, {|variant|
- let ctor_ty = node_id_to_monotype(cx, variant.node.id);
- let arg_tys = if vec::len(variant.node.args) > 0u {
- vec::map(ty_fn_args(cx, ctor_ty), {|a| a.ty})
- } else { [] };
- @{args: arg_tys,
- ctor_ty: ctor_ty,
- id: ast_util::local_def(variant.node.id)}
- })
- }
- }
+ ast_map::node_item(@{node: ast::item_tag(variants, _), _}) {
+ @vec::map(variants, {|variant|
+ let ctor_ty = node_id_to_monotype(cx, variant.node.id);
+ let arg_tys = if vec::len(variant.node.args) > 0u {
+ vec::map(ty_fn_args(cx, ctor_ty), {|a| a.ty})
+ } else { [] };
+ @{args: arg_tys,
+ ctor_ty: ctor_ty,
+ id: ast_util::local_def(variant.node.id)}
+ })
}
}
};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
- ast::item_iface(tps, methods) {
+ ast::item_iface(tps, ms) {
let t = ty::mk_named(tcx, ty::mk_iface(tcx, local_def(it.id),
mk_ty_params(tcx, tps)),
@it.ident);
let tpt = {kinds: ty_param_kinds(tps), ty: t};
tcx.tcache.insert(local_def(it.id), tpt);
+ ty::store_iface_methods(tcx, it.id, @vec::map(ms, {|m|
+ ty_of_ty_method(tcx, m_collect, m)
+ }));
ret tpt;
}
ast::item_impl(_, _, _, _) | ast::item_mod(_) |
ret tpt;
}
fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method {
- {ident: m.ident, fty: ty_of_fn_decl(tcx, mode, m.decl)}
+ {ident: m.ident, tps: vec::map(m.tps, {|tp| tp.kind}),
+ fty: ty_of_fn_decl(tcx, mode, m.decl)}
}
fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method)
-> ty::method {
- {ident: m.ident, fty: ty_of_fn_decl(tcx, mode, m.decl)}
+ {ident: m.ident, tps: vec::map(m.tps, {|tp| tp.kind}),
+ fty: ty_of_fn_decl(tcx, mode, m.decl)}
}
fn ty_of_obj(tcx: ty::ctxt, mode: mode, id: ast::ident, ob: ast::_obj,
ty_params: [ast::ty_param]) -> ty::ty_param_kinds_and_ty {
// record projection work on type inferred arguments.
unify(fcx, expr.span, expected, fty);
- check_fn1(fcx.ccx, decl, body, expr.id, some(fcx));
+ check_fn(fcx.ccx, decl, body, expr.id, some(fcx));
}
fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
}
fn check_fn(ccx: @crate_ctxt,
- decl: ast::fn_decl,
- body: ast::blk,
- id: ast::node_id,
- old_fcx: option::t<@fn_ctxt>) {
- check_fn1(ccx, decl, body, id, old_fcx);
-}
-
-fn check_fn1(ccx: @crate_ctxt,
decl: ast::fn_decl,
body: ast::blk,
id: ast::node_id,
// Now remove the info from the stack.
vec::pop(ccx.self_infos);
}
- ast::item_impl(_, _, ty, ms) {
+ ast::item_impl(_, ifce, ty, ms) {
ccx.self_infos += [self_impl(ast_ty_to_ty(ccx.tcx, m_check, ty))];
- for m in ms { check_method(ccx, m); }
+ let my_methods = vec::map(ms, {|m|
+ check_method(ccx, m);
+ ty_of_method(ccx.tcx, m_check, m)
+ });
vec::pop(ccx.self_infos);
+ alt ifce {
+ some(ty) {
+ alt ty::struct(ccx.tcx, ast_ty_to_ty(ccx.tcx, m_check, ty)) {
+ ty::ty_iface(did, tys) {
+ for if_m in *ty::iface_methods(ccx.tcx, did) {
+ alt vec::find(my_methods, {|m| if_m.ident == m.ident}) {
+ some(m) {
+ if !ty::same_method(ccx.tcx, m, if_m) {
+ ccx.tcx.sess.span_err(
+ ty.span, "method " + if_m.ident +
+ " has the wrong type");
+ }
+ }
+ none. {
+ ccx.tcx.sess.span_err(ty.span, "missing method " +
+ if_m.ident);
+ }
+ }
+ }
+ }
+ _ {
+ ccx.tcx.sess.span_err(ty.span, "can only implement interface \
+ types");
+ }
+ }
+ }
+ _ {}
+ }
}
_ {/* nothing to do */ }
}
type ty_field = spanned<ty_field_>;
-type ty_method = {ident: ident, decl: fn_decl, span: span};
+type ty_method = {ident: ident, decl: fn_decl, tps: [ty_param], span: span};
tag int_ty { ty_i; ty_char; ty_i8; ty_i16; ty_i32; ty_i64; }
constraints: constrs});
}
-fn parse_ty_methods(p: parser) -> [ast::ty_method] {
- fn parse_method_sig(p: parser) -> ast::ty_method {
+fn parse_ty_methods(p: parser, allow_tps: bool) -> [ast::ty_method] {
+ parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p|
let flo = p.get_lo_pos();
let proto: ast::proto = parse_method_proto(p);
let ident = parse_value_ident(p);
+ let tps = allow_tps ? parse_ty_params(p) : [];
let f = parse_ty_fn(proto, p), fhi = p.get_last_hi_pos();
expect(p, token::SEMI);
alt f {
ast::ty_fn(d) {
- {ident: ident, decl: d, span: ast_util::mk_sp(flo, fhi)}
+ {ident: ident, decl: d, tps: tps,
+ span: ast_util::mk_sp(flo, fhi)}
}
}
- }
- parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(),
- parse_method_sig, p).node
+ }, p).node
}
fn parse_mt(p: parser) -> ast::mt {
} else if eat_word(p, "sendfn") {
t = parse_ty_fn(ast::proto_send, p);
} else if eat_word(p, "obj") {
- t = ast::ty_obj(parse_ty_methods(p));
+ t = ast::ty_obj(parse_ty_methods(p, false));
} else if p.peek() == token::MOD_SEP || is_ident(p.peek()) {
let path = parse_path(p);
t = ast::ty_path(path, p.get_id());
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.get_last_lo_pos(), ident = parse_ident(p),
- tps = parse_ty_params(p), meths = parse_ty_methods(p);
+ tps = parse_ty_params(p), meths = parse_ty_methods(p, true);
ret mk_item(p, lo, p.get_last_hi_pos(), ident,
ast::item_iface(tps, meths), attrs);
}