about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-02-17 16:23:31 -0800
committerPatrick Walton <pcwalton@mimiga.net>2011-02-17 16:23:31 -0800
commit10befcd9a4d9f68e2dbec84c4a86450a021143fb (patch)
tree7485ae8b66f3349e3987b480d4be44b34e01af5b
parent79d3ceaac0b4a6ca83f0ff7b8b533649fc5165a1 (diff)
downloadrust-10befcd9a4d9f68e2dbec84c4a86450a021143fb.tar.gz
rust-10befcd9a4d9f68e2dbec84c4a86450a021143fb.zip
Add type parameters to tag types
-rw-r--r--src/comp/middle/trans.rs6
-rw-r--r--src/comp/middle/ty.rs87
-rw-r--r--src/comp/middle/typeck.rs38
-rw-r--r--src/test/run-pass/generic-tag.rs2
4 files changed, 99 insertions, 34 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 62b5a41510c..9d336f221d8 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -490,7 +490,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef {
         }
         case (ty.ty_char) { ret T_char(); }
         case (ty.ty_str) { ret T_ptr(T_str()); }
-        case (ty.ty_tag(?tag_id)) {
+        case (ty.ty_tag(?tag_id, _)) {
             ret llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth);
         }
         case (ty.ty_box(?t)) {
@@ -1445,7 +1445,9 @@ fn iter_structural_ty(@block_ctxt cx,
                 i += 1;
             }
         }
-        case (ty.ty_tag(?tid)) {
+        case (ty.ty_tag(?tid, _)) {
+            // TODO: type params!
+
             check (cx.fcx.ccx.tags.contains_key(tid));
             auto info = cx.fcx.ccx.tags.get(tid);
             auto n_variants = _vec.len[tup(ast.def_id,arity)](info.variants);
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index adda5a8cc1e..e8f5b04684d 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -32,7 +32,7 @@ tag sty {
     ty_machine(util.common.ty_mach);
     ty_char;
     ty_str;
-    ty_tag(ast.def_id);
+    ty_tag(ast.def_id, vec[@t]);
     ty_box(@t);
     ty_vec(@t);
     ty_tup(vec[@t]);
@@ -42,7 +42,7 @@ tag sty {
     ty_obj(vec[method]);
     ty_var(int);                                    // ephemeral type var
     ty_local(ast.def_id);                           // type of a local var
-    ty_param(ast.def_id);                           // fn type param
+    ty_param(ast.def_id);                           // fn/tag type param
     ty_type;
     ty_native;
     // TODO: ty_fn_arg(@t), for a possibly-aliased function argument
@@ -235,9 +235,14 @@ fn ty_to_str(&@t typ) -> str {
             s = "rec(" + _str.connect(strs, ",") + ")";
         }
 
-        case (ty_tag(_)) {
+        case (ty_tag(_, ?tps)) {
             // The user should never see this if the cname is set properly!
             s = "<tag>";
+            if (_vec.len[@t](tps) > 0u) {
+                auto f = ty_to_str;
+                auto strs = _vec.map[@t,str](f, tps);
+                s += "[" + _str.connect(strs, ",") + "]";
+            }
         }
 
         case (ty_fn(?inputs, ?output)) {
@@ -291,7 +296,6 @@ fn fold_ty(ty_fold fld, @t ty) -> @t {
         case (ty_machine(_))    { ret fld.fold_simple_ty(ty); }
         case (ty_char)          { ret fld.fold_simple_ty(ty); }
         case (ty_str)           { ret fld.fold_simple_ty(ty); }
-        case (ty_tag(_))        { ret fld.fold_simple_ty(ty); }
         case (ty_type)          { ret fld.fold_simple_ty(ty); }
         case (ty_native)        { ret fld.fold_simple_ty(ty); }
         case (ty_box(?subty)) {
@@ -300,6 +304,13 @@ fn fold_ty(ty_fold fld, @t ty) -> @t {
         case (ty_vec(?subty)) {
             ret rewrap(ty, ty_vec(fold_ty(fld, subty)));
         }
+        case (ty_tag(?tid, ?subtys)) {
+            let vec[@t] new_subtys = vec();
+            for (@t subty in subtys) {
+                new_subtys += vec(fold_ty(fld, subty));
+            }
+            ret rewrap(ty, ty_tag(tid, new_subtys));
+        }
         case (ty_tup(?subtys)) {
             let vec[@t] new_subtys = vec();
             for (@t subty in subtys) {
@@ -364,23 +375,23 @@ fn type_is_nil(@t ty) -> bool {
 
 fn type_is_structural(@t ty) -> bool {
     alt (ty.struct) {
-        case (ty_tup(_)) { ret true; }
-        case (ty_rec(_)) { ret true; }
-        case (ty_tag(_)) { ret true; }
-        case (ty_fn(_,_)) { ret true; }
-        case (ty_obj(_)) { ret true; }
-        case (_) { ret false; }
+        case (ty_tup(_))    { ret true; }
+        case (ty_rec(_))    { ret true; }
+        case (ty_tag(_,_))  { ret true; }
+        case (ty_fn(_,_))   { ret true; }
+        case (ty_obj(_))    { ret true; }
+        case (_)            { ret false; }
     }
     fail;
 }
 
 fn type_is_tup_like(@t ty) -> bool {
     alt (ty.struct) {
-        case (ty_box(_)) { ret true; }
-        case (ty_tup(_)) { ret true; }
-        case (ty_rec(_)) { ret true; }
-        case (ty_tag(_)) { ret true; }
-        case (_) { ret false; }
+        case (ty_box(_))    { ret true; }
+        case (ty_tup(_))    { ret true; }
+        case (ty_rec(_))    { ret true; }
+        case (ty_tag(_,_))  { ret true; }
+        case (_)            { ret false; }
     }
     fail;
 }
@@ -641,8 +652,13 @@ fn item_ty(@ast.item it) -> ty_params_and_ty {
             result_ty = ann_to_type(ann);
         }
         case (ast.item_tag(_, _, ?tps, ?did)) {
+            // Create a new generic polytype.
             ty_params = tps;
-            result_ty = plain_ty(ty_tag(did));
+            let vec[@t] subtys = vec();
+            for (ast.ty_param tp in tps) {
+                subtys += vec(plain_ty(ty_param(tp.id)));
+            }
+            result_ty = plain_ty(ty_tag(did, subtys));
         }
         case (ast.item_obj(_, _, ?tps, _, ?ann)) {
             ty_params = tps;
@@ -1001,13 +1017,42 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
             case (ty.ty_type)       { ret struct_cmp(expected, actual); }
             case (ty.ty_native)     { ret struct_cmp(expected, actual); }
 
-            case (ty.ty_tag(?expected_id)) {
+            case (ty.ty_tag(?expected_id, ?expected_tps)) {
                 alt (actual.struct) {
-                    case (ty.ty_tag(?actual_id)) {
-                        if (expected_id._0 == actual_id._0 &&
-                                expected_id._1 == actual_id._1) {
-                            ret ures_ok(expected);
+                    case (ty.ty_tag(?actual_id, ?actual_tps)) {
+                        if (expected_id._0 != actual_id._0 ||
+                                expected_id._1 != actual_id._1) {
+                            ret ures_err(terr_mismatch, expected, actual);
+                        }
+
+                        // TODO: factor this cruft out, see the TODO in the
+                        // ty.ty_tup case
+                        let vec[@ty.t] result_tps = vec();
+                        auto i = 0u;
+                        auto expected_len = _vec.len[@ty.t](expected_tps);
+                        while (i < expected_len) {
+                            auto expected_tp = expected_tps.(i);
+                            auto actual_tp = actual_tps.(i);
+
+                            auto result = unify_step(bindings,
+                                                     expected_tp,
+                                                     actual_tp,
+                                                     handler);
+
+                            alt (result) {
+                                case (ures_ok(?rty)) {
+                                    append[@ty.t](result_tps, rty);
+                                }
+                                case (_) {
+                                    ret result;
+                                }
+                            }
+
+                            i += 1u;
                         }
+
+                        ret ures_ok(plain_ty(ty.ty_tag(expected_id,
+                                                       result_tps)));
                     }
                     case (_) { /* fall through */ }
                 }
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 3dab25a7e5e..aa5e9fe5a7a 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -430,8 +430,13 @@ fn collect_item_types(session.session sess, @ast.crate crate)
                 ret ty_;
             }
 
-            case (ast.item_tag(_, _, _, ?def_id)) {
-                auto t = plain_ty(ty.ty_tag(def_id));
+            case (ast.item_tag(_, _, ?tps, ?def_id)) {
+                // Create a new generic polytype.
+                let vec[@ty.t] subtys = vec();
+                for (ast.ty_param tp in tps) {
+                    subtys += vec(plain_ty(ty.ty_param(tp.id)));
+                }
+                auto t = plain_ty(ty.ty_tag(def_id, subtys));
                 item_to_ty.insert(def_id, t);
                 ret t;
             }
@@ -468,15 +473,23 @@ fn collect_item_types(session.session sess, @ast.crate crate)
     fn get_tag_variant_types(@ty_item_table id_to_ty_item,
                              @ty_table item_to_ty,
                              &ast.def_id tag_id,
-                             &vec[ast.variant] variants) -> vec[ast.variant] {
+                             &vec[ast.variant] variants,
+                             &vec[ast.ty_param] ty_params)
+            -> vec[ast.variant] {
         let vec[ast.variant] result = vec();
 
+        // Create a set of parameter types shared among all the variants.
+        let vec[@ty.t] ty_param_tys = vec();
+        for (ast.ty_param tp in ty_params) {
+            ty_param_tys += vec(plain_ty(ty.ty_param(tp.id)));
+        }
+
         for (ast.variant variant in variants) {
-            // Nullary tag constructors get truned into constants; n-ary tag
+            // Nullary tag constructors get turned into constants; n-ary tag
             // constructors get turned into functions.
             auto result_ty;
             if (_vec.len[ast.variant_arg](variant.args) == 0u) {
-                result_ty = plain_ty(ty.ty_tag(tag_id));
+                result_ty = plain_ty(ty.ty_tag(tag_id, ty_param_tys));
             } else {
                 // As above, tell ast_ty_to_ty() that trans_ty_item_to_ty()
                 // should be called to resolve named types.
@@ -487,7 +500,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
                     auto arg_ty = ast_ty_to_ty(f, va.ty);
                     args += vec(rec(mode=ast.alias, ty=arg_ty));
                 }
-                auto tag_t = plain_ty(ty.ty_tag(tag_id));
+                auto tag_t = plain_ty(ty.ty_tag(tag_id, ty_param_tys));
                 result_ty = plain_ty(ty.ty_fn(args, tag_t));
             }
 
@@ -674,7 +687,9 @@ fn collect_item_types(session.session sess, @ast.crate crate)
                      ast.def_id id) -> @ast.item {
         auto variants_t = get_tag_variant_types(e.id_to_ty_item,
                                                 e.item_to_ty,
-                                                id, variants);
+                                                id,
+                                                variants,
+                                                ty_params);
         auto item = ast.item_tag(i, variants_t, ty_params, id);
         ret @fold.respan[ast.item_](sp, item);
     }
@@ -857,7 +872,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat {
 
             auto subpats_len = _vec.len[@ast.pat](subpats);
             alt (variant_ty.struct) {
-                case (ty.ty_tag(_)) {
+                case (ty.ty_tag(_, _)) {
                     // Nullary tag variant.
                     check (subpats_len == 0u);
                     p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t));
@@ -1198,7 +1213,9 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
                 }
 
                 // Nullary variants have tag types.
-                case (ty.ty_tag(?tid)) {
+                case (ty.ty_tag(?tid, _)) {
+                    // TODO: ty params
+
                     auto subpats_len = _vec.len[@ast.pat](subpats);
                     if (subpats_len > 0u) {
                         // TODO: pluralize properly
@@ -1212,7 +1229,8 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
                         fail;   // TODO: recover
                     }
 
-                    auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid)));
+                    let vec[@ty.t] tys = vec(); // FIXME
+                    auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid, tys)));
                     new_pat = ast.pat_tag(p, subpats, vdef_opt, ann);
                 }
             }
diff --git a/src/test/run-pass/generic-tag.rs b/src/test/run-pass/generic-tag.rs
index 1fd88255a14..68d7c18f8d2 100644
--- a/src/test/run-pass/generic-tag.rs
+++ b/src/test/run-pass/generic-tag.rs
@@ -6,4 +6,4 @@ tag option[T] {
 fn main() {
   let option[int] a = some[int](@10);
   a = none[int];
-}
\ No newline at end of file
+}