Skip to content

Commit 6a16f57

Browse files
committed
Get a very primitive form of typechecking/resolving to work for impls
No conflict resolution or polymorphism yet. Issue #1227
1 parent 888bc80 commit 6a16f57

File tree

3 files changed

+93
-62
lines changed

3 files changed

+93
-62
lines changed

src/comp/middle/resolve.rs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import option::{some, none, is_none, is_some};
1919
import syntax::print::pprust::*;
2020

2121
export resolve_crate;
22-
export def_map, ext_map, exp_map, impl_map;
22+
export def_map, ext_map, exp_map, impl_map, iscopes;
2323

2424
// Resolving happens in two passes. The first pass collects defids of all
2525
// (internal) imports and modules, so that they can be looked up when needed,
@@ -48,7 +48,7 @@ tag import_state {
4848
resolved(option::t<def>, /* value */
4949
option::t<def>, /* type */
5050
option::t<def>, /* module */
51-
@[def_id],
51+
@[@ast::item],
5252
/* used for reporting unused import warning */
5353
ast::ident, codemap::span);
5454
}
@@ -487,7 +487,7 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
487487
ids: [ast::ident], sp: codemap::span, sc: scopes) {
488488
fn register(e: env, id: node_id, cx: ctxt, sp: codemap::span,
489489
name: ast::ident, lookup: block(namespace) -> option::t<def>,
490-
impls: [def_id]) {
490+
impls: [@ast::item]) {
491491
let val = lookup(ns_value), typ = lookup(ns_type),
492492
md = lookup(ns_module);
493493
if is_none(val) && is_none(typ) && is_none(md) {
@@ -1623,13 +1623,14 @@ fn check_exports(e: @env) {
16231623
fn resolve_impls(e: @env, c: @ast::crate) {
16241624
visit::visit_crate(*c, nil, visit::mk_vt(@{
16251625
visit_block: bind visit_block_with_impl_scope(e, _, _, _),
1626-
visit_item: bind visit_item_with_impl_scope(e, _, _, _),
1626+
visit_mod: bind visit_mod_with_impl_scope(e, _, _, _, _),
16271627
visit_expr: bind resolve_impl_in_expr(e, _, _, _)
16281628
with *visit::default_visitor()
16291629
}));
16301630
}
16311631

1632-
fn find_impls_in_view_item(e: env, vi: @ast::view_item, &impls: [def_id]) {
1632+
fn find_impls_in_view_item(e: env, vi: @ast::view_item,
1633+
&impls: [@ast::item]) {
16331634
alt vi.node {
16341635
ast::view_item_import(ident, _, id) {
16351636
// FIXME if single name, simply look in our own iscope
@@ -1658,20 +1659,20 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item, &impls: [def_id]) {
16581659
}
16591660
}
16601661

1661-
fn find_impls_in_item(i: @ast::item, &impls: [def_id],
1662+
fn find_impls_in_item(i: @ast::item, &impls: [@ast::item],
16621663
name: option::t<ident>, _dir: dir) {
16631664
// FIXME check exports
16641665
alt i.node {
16651666
ast::item_impl(_, _, _) {
16661667
if alt name { some(n) { n == i.ident } _ { true } } {
1667-
impls += [local_def(i.id)];
1668+
impls += [i];
16681669
}
16691670
}
16701671
_ {}
16711672
}
16721673
}
16731674

1674-
fn find_impls_in_mod(e: env, m: def, &impls: [def_id],
1675+
fn find_impls_in_mod(e: env, m: def, &impls: [@ast::item],
16751676
name: option::t<ident>) {
16761677
alt m {
16771678
ast::def_mod(defid) {
@@ -1686,7 +1687,7 @@ fn find_impls_in_mod(e: env, m: def, &impls: [def_id],
16861687
}
16871688
}
16881689

1689-
type iscopes = list<@[def_id]>;
1690+
type iscopes = list<@[@ast::item]>;
16901691

16911692
fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
16921693
v: vt<iscopes>) {
@@ -1704,19 +1705,12 @@ fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
17041705
visit::visit_block(b, sc, v);
17051706
}
17061707

1707-
fn visit_item_with_impl_scope(e: @env, i: @ast::item, sc: iscopes,
1708-
v: vt<iscopes>) {
1709-
let sc = sc;
1710-
alt i.node {
1711-
ast::item_mod(m) {
1712-
let impls = [];
1713-
for vi in m.view_items { find_impls_in_view_item(*e, vi, impls); }
1714-
for i in m.items { find_impls_in_item(i, impls, none, inside); }
1715-
if vec::len(impls) > 0u { sc = cons(@impls, @sc); }
1716-
}
1717-
_ {}
1718-
}
1719-
visit::visit_item(i, sc, v);
1708+
fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, sc: iscopes,
1709+
v: vt<iscopes>) {
1710+
let impls = [];
1711+
for vi in m.view_items { find_impls_in_view_item(*e, vi, impls); }
1712+
for i in m.items { find_impls_in_item(i, impls, none, inside); }
1713+
visit::visit_mod(m, s, vec::len(impls) > 0u ? cons(@impls, @sc) : sc, v);
17201714
}
17211715

17221716
fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {

src/comp/middle/trans.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4949,7 +4949,10 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
49494949
with *extend_path(cx, item.ident)};
49504950
trans_obj(sub_cx, item.span, ob, ctor_id, tps);
49514951
}
4952-
ast::item_impl(_, _, _) { fail "FIXME[impl]"; }
4952+
ast::item_impl(_, _, _) {
4953+
4954+
fail "FIXME[impl]";
4955+
}
49534956
ast::item_res(dtor, dtor_id, tps, ctor_id) {
49544957
trans_res_ctor(cx, item.span, dtor, ctor_id, tps);
49554958

src/comp/middle/typeck.rs

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
457457
tcx.tcache.insert(local_def(it.id), tpt);
458458
ret tpt;
459459
}
460-
ast::item_mod(_) { fail; }
460+
ast::item_impl(_, _, _) | ast::item_mod(_) |
461461
ast::item_native_mod(_) { fail; }
462462
}
463463
}
@@ -689,17 +689,20 @@ mod collect {
689689
}
690690
fn convert(cx: @ctxt, it: @ast::item) {
691691
alt it.node {
692-
ast::item_mod(_) | ast::item_impl(_, _, _) {
693-
// ignore item_mod, it has no type.
694-
}
695-
ast::item_native_mod(native_mod) {
696-
// do nothing, as native modules have no types.
697-
}
692+
// These don't define types.
693+
ast::item_mod(_) | ast::item_native_mod(_) {}
698694
ast::item_tag(variants, ty_params) {
699695
let tpt = ty_of_item(cx.tcx, m_collect, it);
700696
write::ty_only(cx.tcx, it.id, tpt.ty);
701697
get_tag_variant_types(cx, local_def(it.id), variants, ty_params);
702698
}
699+
ast::item_impl(_, _, ms) {
700+
for m in ms {
701+
write::ty_only(cx.tcx, m.node.id,
702+
ty::method_ty_to_fn_ty(cx.tcx, ty_of_method(
703+
cx.tcx, m_collect, m)));
704+
}
705+
}
703706
ast::item_obj(object, ty_params, ctor_id) {
704707
// Now we need to call ty_of_obj_ctor(); this is the type that
705708
// we write into the table for this item.
@@ -714,8 +717,8 @@ mod collect {
714717
// ty_of_obj().)
715718
let method_types = ty_of_obj_methods(cx.tcx, m_collect, object);
716719
let i = 0u;
717-
while i < vec::len::<@ast::method>(object.methods) {
718-
write::ty_only(cx.tcx, object.methods[i].node.id,
720+
for m in object.methods {
721+
write::ty_only(cx.tcx, m.node.id,
719722
ty::method_ty_to_fn_ty(cx.tcx,
720723
method_types[i]));
721724
i += 1u;
@@ -919,8 +922,6 @@ fn variant_arg_types(ccx: @crate_ctxt, _sp: span, vid: ast::def_id,
919922
let tpt = ty::lookup_item_type(ccx.tcx, vid);
920923
alt ty::struct(ccx.tcx, tpt.ty) {
921924
ty::ty_fn(_, ins, _, _, _) {
922-
923-
924925
// N-ary variant.
925926
for arg: ty::arg in ins {
926927
let arg_ty =
@@ -930,7 +931,6 @@ fn variant_arg_types(ccx: @crate_ctxt, _sp: span, vid: ast::def_id,
930931
}
931932
_ {
932933
// Nullary variant. Do nothing, as there are no arguments.
933-
934934
}
935935
}
936936
/* result is a vector of the *expected* types of all the fields */
@@ -2144,35 +2144,70 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
21442144
}
21452145
}
21462146
ast::expr_field(base, field) {
2147+
// FIXME proper type compare, notice conflicts
2148+
fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
2149+
name: ast::ident, ty: ty::t)
2150+
-> option::t<@ast::method> {
2151+
let result = none;
2152+
std::list::iter(isc) {|impls|
2153+
for im in *impls {
2154+
alt im.node {
2155+
ast::item_impl(_, slf, mthds) {
2156+
let self_ty = ast_ty_to_ty_crate(fcx.ccx, slf);
2157+
alt unify::unify(fcx, ty, self_ty) {
2158+
ures_ok(_) {}
2159+
_ { cont; }
2160+
}
2161+
for m in mthds {
2162+
if m.node.ident == name {
2163+
result = some(m);
2164+
ret;
2165+
}
2166+
}
2167+
}
2168+
}
2169+
}
2170+
}
2171+
result
2172+
}
21472173
bot |= check_expr(fcx, base);
21482174
let base_t = expr_ty(tcx, base);
2149-
base_t = do_autoderef(fcx, expr.span, base_t);
2150-
alt structure_of(fcx, expr.span, base_t) {
2151-
ty::ty_rec(fields) {
2152-
let ix: uint = ty::field_idx(tcx.sess, expr.span, field, fields);
2153-
if ix >= vec::len::<ty::field>(fields) {
2154-
tcx.sess.span_fatal(expr.span, "bad index on record");
2155-
}
2156-
write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
2157-
}
2158-
ty::ty_obj(methods) {
2159-
let ix: uint =
2160-
ty::method_idx(tcx.sess, expr.span, field, methods);
2161-
if ix >= vec::len::<ty::method>(methods) {
2162-
tcx.sess.span_fatal(expr.span, "bad index on obj");
2163-
}
2164-
let meth = methods[ix];
2165-
let t =
2166-
ty::mk_fn(tcx, meth.proto, meth.inputs, meth.output, meth.cf,
2167-
meth.constrs);
2168-
write::ty_only_fixup(fcx, id, t);
2175+
let iscope = fcx.ccx.impl_map.get(expr.id);
2176+
alt lookup_method(fcx, iscope, field, base_t) {
2177+
some(method) {
2178+
let mt = ty_of_method(fcx.ccx.tcx, m_check, method);
2179+
let f_ty = ty::mk_fn(fcx.ccx.tcx, mt.proto, mt.inputs,
2180+
mt.output, mt.cf, mt.constrs);
2181+
write::ty_only_fixup(fcx, id, f_ty);
21692182
}
21702183
_ {
2171-
let t_err = resolve_type_vars_if_possible(fcx, base_t);
2172-
let msg =
2173-
#fmt["attempted field access on type %s",
2174-
ty_to_str(tcx, t_err)];
2175-
tcx.sess.span_fatal(expr.span, msg);
2184+
base_t = do_autoderef(fcx, expr.span, base_t);
2185+
alt structure_of(fcx, expr.span, base_t) {
2186+
ty::ty_rec(fields) {
2187+
let ix = ty::field_idx(tcx.sess, expr.span, field, fields);
2188+
if ix >= vec::len::<ty::field>(fields) {
2189+
tcx.sess.span_fatal(expr.span, "bad index on record");
2190+
}
2191+
write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
2192+
}
2193+
ty::ty_obj(methods) {
2194+
let ix = ty::method_idx(tcx.sess, expr.span, field, methods);
2195+
if ix >= vec::len::<ty::method>(methods) {
2196+
tcx.sess.span_fatal(expr.span, "bad index on obj");
2197+
}
2198+
let meth = methods[ix];
2199+
let t = ty::mk_fn(tcx, meth.proto, meth.inputs, meth.output,
2200+
meth.cf, meth.constrs);
2201+
write::ty_only_fixup(fcx, id, t);
2202+
}
2203+
_ {
2204+
let t_err = resolve_type_vars_if_possible(fcx, base_t);
2205+
let msg = #fmt["attempted field access on type %s, but no \
2206+
method implementation was found",
2207+
ty_to_str(tcx, t_err)];
2208+
tcx.sess.span_fatal(expr.span, msg);
2209+
}
2210+
}
21762211
}
21772212
}
21782213
}
@@ -2602,13 +2637,12 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
26022637
ast::item_obj(ob, _, _) {
26032638
// We're entering an object, so gather up the info we need.
26042639
ccx.obj_infos += [regular_obj(ob.fields, it.id)];
2605-
26062640
// Typecheck the methods.
26072641
for method: @ast::method in ob.methods { check_method(ccx, method); }
2608-
26092642
// Now remove the info from the stack.
26102643
vec::pop::<obj_info>(ccx.obj_infos);
26112644
}
2645+
ast::item_impl(_, _, ms) { for m in ms { check_method(ccx, m); } }
26122646
_ {/* nothing to do */ }
26132647
}
26142648
}

0 commit comments

Comments
 (0)