about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-12-02 10:15:21 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2011-12-16 11:46:57 +0100
commit6a16f57c0a3f37d86b4c8e074f0796669fcd9528 (patch)
tree36c18a257c443174f94678c0597785b749c5dc59 /src/comp/middle
parent888bc80025262286f2270442cea86e20e60d5430 (diff)
downloadrust-6a16f57c0a3f37d86b4c8e074f0796669fcd9528.tar.gz
rust-6a16f57c0a3f37d86b4c8e074f0796669fcd9528.zip
Get a very primitive form of typechecking/resolving to work for impls
No conflict resolution or polymorphism yet.

Issue #1227
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/resolve.rs38
-rw-r--r--src/comp/middle/trans.rs5
-rw-r--r--src/comp/middle/typeck.rs112
3 files changed, 93 insertions, 62 deletions
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 4121771e8b6..22d5945a792 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -19,7 +19,7 @@ import option::{some, none, is_none, is_some};
 import syntax::print::pprust::*;
 
 export resolve_crate;
-export def_map, ext_map, exp_map, impl_map;
+export def_map, ext_map, exp_map, impl_map, iscopes;
 
 // Resolving happens in two passes. The first pass collects defids of all
 // (internal) imports and modules, so that they can be looked up when needed,
@@ -48,7 +48,7 @@ tag import_state {
     resolved(option::t<def>, /* value */
              option::t<def>, /* type */
              option::t<def>, /* module */
-             @[def_id],
+             @[@ast::item],
              /* used for reporting unused import warning */
              ast::ident, codemap::span);
 }
@@ -487,7 +487,7 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
                   ids: [ast::ident], sp: codemap::span, sc: scopes) {
     fn register(e: env, id: node_id, cx: ctxt, sp: codemap::span,
                 name: ast::ident, lookup: block(namespace) -> option::t<def>,
-                impls: [def_id]) {
+                impls: [@ast::item]) {
         let val = lookup(ns_value), typ = lookup(ns_type),
             md = lookup(ns_module);
         if is_none(val) && is_none(typ) && is_none(md) {
@@ -1623,13 +1623,14 @@ fn check_exports(e: @env) {
 fn resolve_impls(e: @env, c: @ast::crate) {
     visit::visit_crate(*c, nil, visit::mk_vt(@{
         visit_block: bind visit_block_with_impl_scope(e, _, _, _),
-        visit_item: bind visit_item_with_impl_scope(e, _, _, _),
+        visit_mod: bind visit_mod_with_impl_scope(e, _, _, _, _),
         visit_expr: bind resolve_impl_in_expr(e, _, _, _)
         with *visit::default_visitor()
     }));
 }
 
-fn find_impls_in_view_item(e: env, vi: @ast::view_item, &impls: [def_id]) {
+fn find_impls_in_view_item(e: env, vi: @ast::view_item,
+                           &impls: [@ast::item]) {
     alt vi.node {
       ast::view_item_import(ident, _, id) {
         // 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]) {
     }
 }
 
-fn find_impls_in_item(i: @ast::item, &impls: [def_id],
+fn find_impls_in_item(i: @ast::item, &impls: [@ast::item],
                       name: option::t<ident>, _dir: dir) {
     // FIXME check exports
     alt i.node {
       ast::item_impl(_, _, _) {
         if alt name { some(n) { n == i.ident } _ { true } } {
-            impls += [local_def(i.id)];
+            impls += [i];
         }
       }
       _ {}
     }
 }
 
-fn find_impls_in_mod(e: env, m: def, &impls: [def_id],
+fn find_impls_in_mod(e: env, m: def, &impls: [@ast::item],
                      name: option::t<ident>) {
     alt m {
       ast::def_mod(defid) {
@@ -1686,7 +1687,7 @@ fn find_impls_in_mod(e: env, m: def, &impls: [def_id],
     }
 }
 
-type iscopes = list<@[def_id]>;
+type iscopes = list<@[@ast::item]>;
 
 fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
                                v: vt<iscopes>) {
@@ -1704,19 +1705,12 @@ fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
     visit::visit_block(b, sc, v);
 }
 
-fn visit_item_with_impl_scope(e: @env, i: @ast::item, sc: iscopes,
-                              v: vt<iscopes>) {
-    let sc = sc;
-    alt i.node {
-      ast::item_mod(m) {
-        let impls = [];
-        for vi in m.view_items { find_impls_in_view_item(*e, vi, impls); }
-        for i in m.items { find_impls_in_item(i, impls, none, inside); }
-        if vec::len(impls) > 0u { sc = cons(@impls, @sc); }
-      }
-      _ {}
-    }
-    visit::visit_item(i, sc, v);
+fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, sc: iscopes,
+                             v: vt<iscopes>) {
+    let impls = [];
+    for vi in m.view_items { find_impls_in_view_item(*e, vi, impls); }
+    for i in m.items { find_impls_in_item(i, impls, none, inside); }
+    visit::visit_mod(m, s, vec::len(impls) > 0u ? cons(@impls, @sc) : sc, v);
 }
 
 fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index bd25cc4e9bf..a0493b8cbc8 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -4949,7 +4949,10 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
                  with *extend_path(cx, item.ident)};
         trans_obj(sub_cx, item.span, ob, ctor_id, tps);
       }
-      ast::item_impl(_, _, _) { fail "FIXME[impl]"; }
+      ast::item_impl(_, _, _) {
+        
+        fail "FIXME[impl]";
+      }
       ast::item_res(dtor, dtor_id, tps, ctor_id) {
         trans_res_ctor(cx, item.span, dtor, ctor_id, tps);
 
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 1150f4637de..10814ed61ae 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -457,7 +457,7 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
         tcx.tcache.insert(local_def(it.id), tpt);
         ret tpt;
       }
-      ast::item_mod(_) { fail; }
+      ast::item_impl(_, _, _) | ast::item_mod(_) |
       ast::item_native_mod(_) { fail; }
     }
 }
@@ -689,17 +689,20 @@ mod collect {
     }
     fn convert(cx: @ctxt, it: @ast::item) {
         alt it.node {
-          ast::item_mod(_) | ast::item_impl(_, _, _) {
-            // ignore item_mod, it has no type.
-          }
-          ast::item_native_mod(native_mod) {
-            // do nothing, as native modules have no types.
-          }
+          // These don't define types.
+          ast::item_mod(_) | ast::item_native_mod(_) {}
           ast::item_tag(variants, ty_params) {
             let tpt = ty_of_item(cx.tcx, m_collect, it);
             write::ty_only(cx.tcx, it.id, tpt.ty);
             get_tag_variant_types(cx, local_def(it.id), variants, ty_params);
           }
+          ast::item_impl(_, _, ms) {
+            for m in ms {
+                write::ty_only(cx.tcx, m.node.id, 
+                               ty::method_ty_to_fn_ty(cx.tcx, ty_of_method(
+                                   cx.tcx, m_collect, m)));
+            }
+          }
           ast::item_obj(object, ty_params, ctor_id) {
             // Now we need to call ty_of_obj_ctor(); this is the type that
             // we write into the table for this item.
@@ -714,8 +717,8 @@ mod collect {
             // ty_of_obj().)
             let method_types = ty_of_obj_methods(cx.tcx, m_collect, object);
             let i = 0u;
-            while i < vec::len::<@ast::method>(object.methods) {
-                write::ty_only(cx.tcx, object.methods[i].node.id,
+            for m in object.methods {
+                write::ty_only(cx.tcx, m.node.id,
                                ty::method_ty_to_fn_ty(cx.tcx,
                                                       method_types[i]));
                 i += 1u;
@@ -919,8 +922,6 @@ fn variant_arg_types(ccx: @crate_ctxt, _sp: span, vid: ast::def_id,
     let tpt = ty::lookup_item_type(ccx.tcx, vid);
     alt ty::struct(ccx.tcx, tpt.ty) {
       ty::ty_fn(_, ins, _, _, _) {
-
-
         // N-ary variant.
         for arg: ty::arg in ins {
             let arg_ty =
@@ -930,7 +931,6 @@ fn variant_arg_types(ccx: @crate_ctxt, _sp: span, vid: ast::def_id,
       }
       _ {
         // Nullary variant. Do nothing, as there are no arguments.
-
       }
     }
     /* 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,
         }
       }
       ast::expr_field(base, field) {
+        // FIXME proper type compare, notice conflicts
+        fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
+                         name: ast::ident, ty: ty::t)
+            -> option::t<@ast::method> {
+            let result = none;
+            std::list::iter(isc) {|impls|
+                for im in *impls {
+                    alt im.node {
+                      ast::item_impl(_, slf, mthds) {
+                        let self_ty = ast_ty_to_ty_crate(fcx.ccx, slf);
+                        alt unify::unify(fcx, ty, self_ty) {
+                          ures_ok(_) {}
+                          _ { cont; }
+                        }
+                        for m in mthds {
+                            if m.node.ident == name {
+                                result = some(m);
+                                ret;
+                            }
+                        }
+                      }
+                    }
+                }
+            }
+            result
+        }
         bot |= check_expr(fcx, base);
         let base_t = expr_ty(tcx, base);
-        base_t = do_autoderef(fcx, expr.span, base_t);
-        alt structure_of(fcx, expr.span, base_t) {
-          ty::ty_rec(fields) {
-            let ix: uint = ty::field_idx(tcx.sess, expr.span, field, fields);
-            if ix >= vec::len::<ty::field>(fields) {
-                tcx.sess.span_fatal(expr.span, "bad index on record");
-            }
-            write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
-          }
-          ty::ty_obj(methods) {
-            let ix: uint =
-                ty::method_idx(tcx.sess, expr.span, field, methods);
-            if ix >= vec::len::<ty::method>(methods) {
-                tcx.sess.span_fatal(expr.span, "bad index on obj");
-            }
-            let meth = methods[ix];
-            let t =
-                ty::mk_fn(tcx, meth.proto, meth.inputs, meth.output, meth.cf,
-                          meth.constrs);
-            write::ty_only_fixup(fcx, id, t);
+        let iscope = fcx.ccx.impl_map.get(expr.id);
+        alt lookup_method(fcx, iscope, field, base_t) {
+          some(method) {
+            let mt = ty_of_method(fcx.ccx.tcx, m_check, method);
+            let f_ty = ty::mk_fn(fcx.ccx.tcx, mt.proto, mt.inputs,
+                                 mt.output, mt.cf, mt.constrs);
+            write::ty_only_fixup(fcx, id, f_ty);
           }
           _ {
-            let t_err = resolve_type_vars_if_possible(fcx, base_t);
-            let msg =
-                #fmt["attempted field access on type %s",
-                     ty_to_str(tcx, t_err)];
-            tcx.sess.span_fatal(expr.span, msg);
+            base_t = do_autoderef(fcx, expr.span, base_t);
+            alt structure_of(fcx, expr.span, base_t) {
+              ty::ty_rec(fields) {
+                let ix = ty::field_idx(tcx.sess, expr.span, field, fields);
+                if ix >= vec::len::<ty::field>(fields) {
+                    tcx.sess.span_fatal(expr.span, "bad index on record");
+                }
+                write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
+              }
+              ty::ty_obj(methods) {
+                let ix = ty::method_idx(tcx.sess, expr.span, field, methods);
+                if ix >= vec::len::<ty::method>(methods) {
+                    tcx.sess.span_fatal(expr.span, "bad index on obj");
+                }
+                let meth = methods[ix];
+                let t = ty::mk_fn(tcx, meth.proto, meth.inputs, meth.output,
+                                  meth.cf, meth.constrs);
+                write::ty_only_fixup(fcx, id, t);
+              }
+              _ {
+                let t_err = resolve_type_vars_if_possible(fcx, base_t);
+                let msg = #fmt["attempted field access on type %s, but no \
+                                method implementation was found",
+                               ty_to_str(tcx, t_err)];
+                tcx.sess.span_fatal(expr.span, msg);
+              }
+            }
           }
         }
       }
@@ -2602,13 +2637,12 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
       ast::item_obj(ob, _, _) {
         // We're entering an object, so gather up the info we need.
         ccx.obj_infos += [regular_obj(ob.fields, it.id)];
-
         // Typecheck the methods.
         for method: @ast::method in ob.methods { check_method(ccx, method); }
-
         // Now remove the info from the stack.
         vec::pop::<obj_info>(ccx.obj_infos);
       }
+      ast::item_impl(_, _, ms) { for m in ms { check_method(ccx, m); } }
       _ {/* nothing to do */ }
     }
 }