about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-01-06 16:25:04 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-01-06 17:40:05 +0100
commitd23e2052e0187e57b2fe626e5354a77ced29d0cf (patch)
tree612bf3c35a55e3ef5263ad6b5694e6d022339559
parentd214e3df1657e8fa00d475aa5d31d0498f35d337 (diff)
downloadrust-d23e2052e0187e57b2fe626e5354a77ced29d0cf.tar.gz
rust-d23e2052e0187e57b2fe626e5354a77ced29d0cf.zip
Support interface casting in the typechecker
Issue #1437
-rw-r--r--src/comp/middle/resolve.rs2
-rw-r--r--src/comp/middle/typeck.rs38
2 files changed, 34 insertions, 6 deletions
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 9aa57e182cc..bdb4ae67545 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -1892,7 +1892,7 @@ fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, sc: iscopes,
 
 fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
     alt x.node {
-      ast::expr_field(_, _, _) | ast::expr_path(_) {
+      ast::expr_field(_, _, _) | ast::expr_path(_) | ast::expr_cast(_, _) {
         e.impl_map.insert(x.id, sc);
       }
       _ {}
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index d75b04d0787..792867a646e 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -25,6 +25,7 @@ tag method_origin {
     method_static(ast::def_id);
     // iface id, method num, param num, bound num
     method_param(ast::def_id, uint, uint, uint);
+    method_iface;
 }
 type method_map = hashmap<ast::node_id, method_origin>;
 
@@ -1572,6 +1573,16 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
         }
         ret none;
       }
+      ty::ty_iface(did, tps) {
+        for m in *ty::iface_methods(tcx, did) {
+            if m.ident == name {
+                ret some({method_ty: ty::mk_fn(tcx, m.fty),
+                          n_tps: vec::len(*m.tps),
+                          substs: tps,
+                          origin: method_iface});
+            }
+        }
+      }
       _ {}
     }
 
@@ -2192,13 +2203,18 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
                                   ty_to_str(tcx, t_1));
         }
 
-        // FIXME there are more forms of cast to support, eventually.
-        if !(   type_is_scalar(fcx, expr.span, t_e)
-             && type_is_scalar(fcx, expr.span, t_1)) {
-            tcx.sess.span_err(expr.span,
-                              "non-scalar cast: " +
+        alt ty::struct(tcx, t_1) {
+          // This will be looked up later on
+          ty::ty_iface(_, _) {}
+          _ {
+            // FIXME there are more forms of cast to support, eventually.
+            if !(   type_is_scalar(fcx, expr.span, t_e)
+                 && type_is_scalar(fcx, expr.span, t_1)) {
+                tcx.sess.span_err(expr.span, "non-scalar cast: " +
                                   ty_to_str(tcx, t_e) + " as " +
                                   ty_to_str(tcx, t_1));
+            }
+          }
         }
         write::ty_only_fixup(fcx, id, t_1);
       }
@@ -3019,6 +3035,18 @@ mod dict {
               _ {}
             }
           }
+          ast::expr_cast(src, _) {
+            let target_ty = expr_ty(cx.tcx, ex);
+            alt ty::struct(cx.tcx, target_ty) {
+              ty::ty_iface(_, _) {
+                let impls = cx.impl_map.get(ex.id);
+                let dict = lookup_dict(fcx, impls, ex.span,
+                                       expr_ty(cx.tcx, src), target_ty);
+                cx.dict_map.insert(ex.id, @[dict]);
+              }
+              _ {}
+            }
+          }
           ast::expr_fn(ast::proto_block., _, _, _) {}
           ast::expr_fn(_, _, _, _) { ret; }
           _ {}