about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-02-25 12:37:03 -0800
committerPatrick Walton <pcwalton@mimiga.net>2011-02-25 13:44:08 -0800
commit7a1d01effcfa5763bc62aefba40f67ad2130d28d (patch)
tree2e26bf45352b71d1e618f359bf388beae354fb21 /src
parent081c3aa76dd0805767e0233c0cc6ccf313cf44ba (diff)
rustc: Push type parameters down through alt tag patterns; add a test
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/typeck.rs55
-rw-r--r--src/test/run-pass/generic-tag-box-alt.rs19
2 files changed, 68 insertions, 6 deletions
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index ce1c59ec01f..a69d169d7e3 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -919,9 +919,42 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat {
             // acquire here with the type parameters provided to us by
             // "expected".
 
+            // Grab the values for the type parameters of the tag from the
+            // expected type.
+            let vec[@ty.t] typaram_bindings = vec(); // FIXME: typestate botch
+            alt (expected.struct) {
+                case (ty.ty_tag(_, ?tps)) { typaram_bindings = tps; }
+                case (_) {
+                    log "tag pattern didn't have tag type?!";
+                    fail;
+                }
+            }
+
+            // Get the item corresponding to the tag and its type.
             auto vdef = option.get[ast.variant_def](vdef_opt);
             auto variant_ty = fcx.ccx.item_types.get(vdef._1);
 
+            // FIXME: typestate botch
+            let option.t[@ast.item] item_opt = none[@ast.item];
+            alt (fcx.ccx.item_items.get(vdef._0)) {
+                case (any_item_rust(?it)) { item_opt = some[@ast.item](it); }
+                case (_) {
+                    log "tag item isn't a Rust item?!";
+                    fail;
+                }
+            }
+            let @ast.item item = option.get[@ast.item](item_opt);
+
+            // Get the IDs of the type parameters from that item.
+            let vec[ast.ty_param] ty_params = vec(); // FIXME: typestate botch
+            alt (item.node) {
+                case (ast.item_tag(_, _, ?tps, _)) { ty_params = tps; }
+                case (_) {
+                    log "tag's corresponding item isn't a tag?!";
+                    fail;
+                }
+            }
+
             auto subpats_len = _vec.len[@ast.pat](subpats);
             alt (variant_ty.struct) {
                 case (ty.ty_tag(_, _)) {
@@ -930,10 +963,14 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat {
                     p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t));
                 }
                 case (ty.ty_fn(_, ?args, ?tag_ty)) {
+                    // N-ary tag variant.
                     let vec[@ast.pat] new_subpats = vec();
                     auto i = 0u;
                     for (arg a in args) {
-                        auto new_subpat = demand_pat(fcx, a.ty, subpats.(i));
+                        auto arg_ty = ty.substitute_ty_params(ty_params,
+                            typaram_bindings, a.ty);
+                        auto new_subpat = demand_pat(fcx, arg_ty,
+                                                     subpats.(i));
                         new_subpats += vec(new_subpat);
                         i += 1u;
                     }
@@ -1260,14 +1297,13 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
                         new_subpats += vec(check_pat(fcx, subpat));
                     }
 
-                    auto ann = ast.ann_type(tag_ty);
+                    auto tag_ty_g = generalize_ty(fcx.ccx, tag_ty);
+                    auto ann = ast.ann_type(tag_ty_g);
                     new_pat = ast.pat_tag(p, new_subpats, vdef_opt, ann);
                 }
 
                 // Nullary variants have tag types.
-                case (ty.ty_tag(?tid, _)) {
-                    // TODO: ty params
-
+                case (ty.ty_tag(?tid, ?tps)) {
                     auto subpats_len = _vec.len[@ast.pat](subpats);
                     if (subpats_len > 0u) {
                         // TODO: pluralize properly
@@ -1281,7 +1317,14 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
                         fail;   // TODO: recover
                     }
 
-                    let vec[@ty.t] tys = vec(); // FIXME
+                    // Add the appropriate number of type variables.
+                    let vec[@ty.t] tys = vec();
+                    auto i = 0u;
+                    while (i < _vec.len[@ty.t](tps)) {
+                        tys += vec(next_ty_var(fcx.ccx));
+                        i += 1u;
+                    }
+
                     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-box-alt.rs b/src/test/run-pass/generic-tag-box-alt.rs
new file mode 100644
index 00000000000..2727885a161
--- /dev/null
+++ b/src/test/run-pass/generic-tag-box-alt.rs
@@ -0,0 +1,19 @@
+tag foo[T] {
+  arm(@T);
+}
+
+fn altfoo[T](foo[T] f) {
+  auto hit = false;
+  alt (f) {
+    case (arm[T](?x)) {
+      log "in arm";
+      hit = true;
+    }
+  }
+  check (hit);
+}
+
+fn main() {
+  altfoo[int](arm[int](@10));
+}
+