about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-07-29 16:40:23 -0700
committerGraydon Hoare <graydon@mozilla.com>2011-07-29 16:40:30 -0700
commit59c441a66a86d04087f15aaa9d624fb3c24fcb54 (patch)
treeb21b5af66371deab773ec64271ec15dcff6646ff
parenta684f6078f7f67ae7f6396b3f8f58cc6e78bdc4c (diff)
downloadrust-59c441a66a86d04087f15aaa9d624fb3c24fcb54.tar.gz
rust-59c441a66a86d04087f15aaa9d624fb3c24fcb54.zip
Encode, decode, and thread through typechecking all the param kinds, not just the counts.
-rw-r--r--src/comp/metadata/common.rs4
-rw-r--r--src/comp/metadata/csearch.rs2
-rw-r--r--src/comp/metadata/decoder.rs64
-rw-r--r--src/comp/metadata/encoder.rs60
-rw-r--r--src/comp/middle/kind.rs5
-rw-r--r--src/comp/middle/trans.rs16
-rw-r--r--src/comp/middle/ty.rs11
-rw-r--r--src/comp/middle/typeck.rs85
8 files changed, 143 insertions, 104 deletions
diff --git a/src/comp/metadata/common.rs b/src/comp/metadata/common.rs
index e8fce2da7df..065f4dc66bc 100644
--- a/src/comp/metadata/common.rs
+++ b/src/comp/metadata/common.rs
@@ -20,9 +20,9 @@ const tag_items_data: uint = 0x08u;
 
 const tag_items_data_item: uint = 0x09u;
 
-const tag_items_data_item_kind: uint = 0x0au;
+const tag_items_data_item_family: uint = 0x0au;
 
-const tag_items_data_item_ty_param_count: uint = 0x0bu;
+const tag_items_data_item_ty_param_kinds: uint = 0x0bu;
 
 const tag_items_data_item_type: uint = 0x0cu;
 
diff --git a/src/comp/metadata/csearch.rs b/src/comp/metadata/csearch.rs
index a6086704183..7a397fff317 100644
--- a/src/comp/metadata/csearch.rs
+++ b/src/comp/metadata/csearch.rs
@@ -35,7 +35,7 @@ fn get_tag_variants(tcx: ty::ctxt, def: ast::def_id) -> ty::variant_info[] {
     ret decoder::get_tag_variants(cdata, def, tcx, resolver)
 }
 
-fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_count_and_ty {
+fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_kinds_and_ty {
     let cstore = tcx.sess.get_cstore();
     let cnum = def.crate;
     let cdata = cstore::get_crate_data(cstore, cnum).data;
diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs
index ab9c07981b9..45c9dcf3b37 100644
--- a/src/comp/metadata/decoder.rs
+++ b/src/comp/metadata/decoder.rs
@@ -20,6 +20,7 @@ export get_symbol;
 export get_tag_variants;
 export get_type;
 export get_type_param_count;
+export get_type_param_kinds;
 export lookup_defs;
 export get_crate_attributes;
 export list_crate_metadata;
@@ -77,9 +78,9 @@ fn lookup_item(item_id: int, data: &@u8[]) -> ebmlivec::doc {
     ret find_item(item_id, items);
 }
 
-fn item_kind(item: &ebmlivec::doc) -> u8 {
-    let kind = ebmlivec::get_doc(item, tag_items_data_item_kind);
-    ret ebmlivec::doc_as_uint(kind) as u8;
+fn item_family(item: &ebmlivec::doc) -> u8 {
+    let fam = ebmlivec::get_doc(item, tag_items_data_item_family);
+    ret ebmlivec::doc_as_uint(fam) as u8;
 }
 
 fn item_symbol(item: &ebmlivec::doc) -> str {
@@ -113,13 +114,24 @@ fn item_type(item: &ebmlivec::doc, this_cnum: ast::crate_num, tcx: ty::ctxt,
                       def_parser, tcx);
 }
 
-fn item_ty_param_count(item: &ebmlivec::doc) -> uint {
-    let ty_param_count: uint = 0u;
-    let tp = tag_items_data_item_ty_param_count;
-    for each p: ebmlivec::doc  in ebmlivec::tagged_docs(item, tp) {
-        ty_param_count = ebmlivec::vint_at(ebmlivec::doc_data(p), 0u).val;
+fn item_ty_param_kinds(item: &ebmlivec::doc) -> ast::kind[] {
+    let ks: ast::kind[] = ~[];
+    let tp = tag_items_data_item_ty_param_kinds;
+    for each p: ebmlivec::doc in ebmlivec::tagged_docs(item, tp) {
+        let dat : u8[] = ebmlivec::doc_data(p);
+        let vi = ebmlivec::vint_at(dat, 0u);
+        let i = 0u;
+        while i < vi.val {
+            let k = alt dat.(vi.next + i) as char {
+              'u' { ast::kind_unique }
+              's' { ast::kind_shared }
+              'p' { ast::kind_pinned }
+            };
+            ks += ~[k];
+            i += 1u;
+        }
     }
-    ret ty_param_count;
+    ret ks;
 }
 
 fn tag_variant_ids(item: &ebmlivec::doc, this_cnum: ast::crate_num) ->
@@ -162,11 +174,11 @@ fn lookup_defs(data: &@u8[], cnum: ast::crate_num, path: &ast::ident[]) ->
 fn lookup_def(cnum: ast::crate_num, data: @u8[], did_: &ast::def_id) ->
    ast::def {
     let item = lookup_item(did_.node, data);
-    let kind_ch = item_kind(item);
+    let fam_ch = item_family(item);
     let did = {crate: cnum, node: did_.node};
     // We treat references to tags as references to types.
     let def =
-        alt kind_ch as char {
+        alt fam_ch as char {
           'c' { ast::def_const(did) }
           'f' { ast::def_fn(did, ast::impure_fn) }
           'p' { ast::def_fn(did, ast::pure_fn) }
@@ -186,22 +198,26 @@ fn lookup_def(cnum: ast::crate_num, data: @u8[], did_: &ast::def_id) ->
 }
 
 fn get_type(data: @u8[], def: ast::def_id, tcx: &ty::ctxt,
-            extres: &external_resolver) -> ty::ty_param_count_and_ty {
+            extres: &external_resolver) -> ty::ty_param_kinds_and_ty {
     let this_cnum = def.crate;
     let node_id = def.node;
     let item = lookup_item(node_id, data);
     let t = item_type(item, this_cnum, tcx, extres);
-    let tp_count;
-    let kind_ch = item_kind(item);
-    let has_ty_params = kind_has_type_params(kind_ch);
+    let tp_kinds : ast::kind[];
+    let fam_ch = item_family(item);
+    let has_ty_params = family_has_type_params(fam_ch);
     if has_ty_params {
-        tp_count = item_ty_param_count(item);
-    } else { tp_count = 0u; }
-    ret {count: tp_count, ty: t};
+        tp_kinds = item_ty_param_kinds(item);
+    } else { tp_kinds = ~[]; }
+    ret {kinds: tp_kinds, ty: t};
 }
 
 fn get_type_param_count(data: @u8[], id: ast::node_id) -> uint {
-    ret item_ty_param_count(lookup_item(id, data));
+    ret ivec::len(get_type_param_kinds(data, id));
+}
+
+fn get_type_param_kinds(data: @u8[], id: ast::node_id) -> ast::kind[] {
+    ret item_ty_param_kinds(lookup_item(id, data));
 }
 
 fn get_symbol(data: @u8[], id: ast::node_id) -> str {
@@ -235,8 +251,8 @@ fn get_tag_variants(data: &@u8[], def: ast::def_id, tcx: &ty::ctxt,
     ret infos;
 }
 
-fn kind_has_type_params(kind_ch: u8) -> bool {
-    ret alt kind_ch as char {
+fn family_has_type_params(fam_ch: u8) -> bool {
+    ret alt fam_ch as char {
           'c' { false }
           'f' { true }
           'p' { true }
@@ -260,11 +276,11 @@ fn read_path(d: &ebmlivec::doc) -> {path: str, pos: uint} {
 
 fn describe_def(items: &ebmlivec::doc, id: ast::def_id) -> str {
     if id.crate != ast::local_crate { ret "external"; }
-    ret item_kind_to_str(item_kind(find_item(id.node, items)));
+    ret item_family_to_str(item_family(find_item(id.node, items)));
 }
 
-fn item_kind_to_str(kind: u8) -> str {
-    alt kind as char {
+fn item_family_to_str(fam: u8) -> str {
+    alt fam as char {
       'c' { ret "const"; }
       'f' { ret "fn"; }
       'p' { ret "pred"; }
diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs
index f6ad31a41b9..b9a1fa3886a 100644
--- a/src/comp/metadata/encoder.rs
+++ b/src/comp/metadata/encoder.rs
@@ -160,17 +160,25 @@ fn encode_item_paths(ebml_w: &ebmlivec::writer, crate: &@crate) ->
 
 
 // Item info table encoding
-fn encode_kind(ebml_w: &ebmlivec::writer, c: u8) {
-    ebmlivec::start_tag(ebml_w, tag_items_data_item_kind);
+fn encode_family(ebml_w: &ebmlivec::writer, c: u8) {
+    ebmlivec::start_tag(ebml_w, tag_items_data_item_family);
     ebml_w.writer.write(~[c]);
     ebmlivec::end_tag(ebml_w);
 }
 
 fn def_to_str(did: &def_id) -> str { ret #fmt("%d:%d", did.crate, did.node); }
 
-fn encode_type_param_count(ebml_w: &ebmlivec::writer, tps: &ty_param[]) {
-    ebmlivec::start_tag(ebml_w, tag_items_data_item_ty_param_count);
+fn encode_type_param_kinds(ebml_w: &ebmlivec::writer, tps: &ty_param[]) {
+    ebmlivec::start_tag(ebml_w, tag_items_data_item_ty_param_kinds);
     ebmlivec::write_vint(ebml_w.writer, ivec::len[ty_param](tps));
+    for tp: ty_param in tps {
+        let c = alt tp.kind {
+          kind_unique. { 'u' }
+          kind_shared. { 's' }
+          kind_pinned. { 'p' }
+        };
+        ebml_w.writer.write(~[c as u8]);
+    }
     ebmlivec::end_tag(ebml_w);
 }
 
@@ -218,7 +226,7 @@ fn encode_tag_variant_info(ecx: &@encode_ctxt, ebml_w: &ebmlivec::writer,
         index += ~[{val: variant.node.id, pos: ebml_w.writer.tell()}];
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(variant.node.id));
-        encode_kind(ebml_w, 'v' as u8);
+        encode_family(ebml_w, 'v' as u8);
         encode_tag_id(ebml_w, local_def(id));
         encode_type(ecx, ebml_w,
                     node_id_to_monotype(ecx.ccx.tcx, variant.node.id));
@@ -226,7 +234,7 @@ fn encode_tag_variant_info(ecx: &@encode_ctxt, ebml_w: &ebmlivec::writer,
             encode_symbol(ecx, ebml_w, variant.node.id);
         }
         encode_discriminant(ecx, ebml_w, variant.node.id);
-        encode_type_param_count(ebml_w, ty_params);
+        encode_type_param_kinds(ebml_w, ty_params);
         ebmlivec::end_tag(ebml_w);
     }
 }
@@ -237,7 +245,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: &ebmlivec::writer,
       item_const(_, _) {
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
-        encode_kind(ebml_w, 'c' as u8);
+        encode_family(ebml_w, 'c' as u8);
         encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
         encode_symbol(ecx, ebml_w, item.id);
         ebmlivec::end_tag(ebml_w);
@@ -245,10 +253,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: &ebmlivec::writer,
       item_fn(fd, tps) {
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
-        encode_kind(ebml_w,
+        encode_family(ebml_w,
                     alt fd.decl.purity { pure_fn. { 'p' } impure_fn. { 'f' } }
                         as u8);
-        encode_type_param_count(ebml_w, tps);
+        encode_type_param_kinds(ebml_w, tps);
         encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
         encode_symbol(ecx, ebml_w, item.id);
         ebmlivec::end_tag(ebml_w);
@@ -256,28 +264,28 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: &ebmlivec::writer,
       item_mod(_) {
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
-        encode_kind(ebml_w, 'm' as u8);
+        encode_family(ebml_w, 'm' as u8);
         ebmlivec::end_tag(ebml_w);
       }
       item_native_mod(_) {
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
-        encode_kind(ebml_w, 'n' as u8);
+        encode_family(ebml_w, 'n' as u8);
         ebmlivec::end_tag(ebml_w);
       }
       item_ty(_, tps) {
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
-        encode_kind(ebml_w, 'y' as u8);
-        encode_type_param_count(ebml_w, tps);
+        encode_family(ebml_w, 'y' as u8);
+        encode_type_param_kinds(ebml_w, tps);
         encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
         ebmlivec::end_tag(ebml_w);
       }
       item_tag(variants, tps) {
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
-        encode_kind(ebml_w, 't' as u8);
-        encode_type_param_count(ebml_w, tps);
+        encode_family(ebml_w, 't' as u8);
+        encode_type_param_kinds(ebml_w, tps);
         encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, item.id));
         for v: variant  in variants {
             encode_variant_id(ebml_w, local_def(v.node.id));
@@ -290,8 +298,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: &ebmlivec::writer,
 
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(ctor_id));
-        encode_kind(ebml_w, 'y' as u8);
-        encode_type_param_count(ebml_w, tps);
+        encode_family(ebml_w, 'y' as u8);
+        encode_type_param_kinds(ebml_w, tps);
         encode_type(ecx, ebml_w, ty::ty_fn_ret(ecx.ccx.tcx, fn_ty));
         encode_symbol(ecx, ebml_w, item.id);
         ebmlivec::end_tag(ebml_w);
@@ -299,8 +307,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: &ebmlivec::writer,
         index += ~[{val: ctor_id, pos: ebml_w.writer.tell()}];
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(ctor_id));
-        encode_kind(ebml_w, 'f' as u8);
-        encode_type_param_count(ebml_w, tps);
+        encode_family(ebml_w, 'f' as u8);
+        encode_type_param_kinds(ebml_w, tps);
         encode_type(ecx, ebml_w, fn_ty);
         encode_symbol(ecx, ebml_w, ctor_id);
         ebmlivec::end_tag(ebml_w);
@@ -310,16 +318,16 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: &ebmlivec::writer,
 
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
-        encode_kind(ebml_w, 'y' as u8);
-        encode_type_param_count(ebml_w, tps);
+        encode_family(ebml_w, 'y' as u8);
+        encode_type_param_kinds(ebml_w, tps);
         encode_type(ecx, ebml_w, ty::ty_fn_ret(ecx.ccx.tcx, fn_ty));
         ebmlivec::end_tag(ebml_w);
 
         index += ~[{val: ctor_id, pos: ebml_w.writer.tell()}];
         ebmlivec::start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, local_def(ctor_id));
-        encode_kind(ebml_w, 'f' as u8);
-        encode_type_param_count(ebml_w, tps);
+        encode_family(ebml_w, 'f' as u8);
+        encode_type_param_kinds(ebml_w, tps);
         encode_type(ecx, ebml_w, fn_ty);
         encode_symbol(ecx, ebml_w, ctor_id);
         ebmlivec::end_tag(ebml_w);
@@ -333,14 +341,14 @@ fn encode_info_for_native_item(ecx: &@encode_ctxt, ebml_w: &ebmlivec::writer,
     alt nitem.node {
       native_item_ty. {
         encode_def_id(ebml_w, local_def(nitem.id));
-        encode_kind(ebml_w, 'T' as u8);
+        encode_family(ebml_w, 'T' as u8);
         encode_type(ecx, ebml_w,
                     ty::mk_native(ecx.ccx.tcx, local_def(nitem.id)));
       }
       native_item_fn(_, _, tps) {
         encode_def_id(ebml_w, local_def(nitem.id));
-        encode_kind(ebml_w, 'F' as u8);
-        encode_type_param_count(ebml_w, tps);
+        encode_family(ebml_w, 'F' as u8);
+        encode_type_param_kinds(ebml_w, tps);
         encode_type(ecx, ebml_w, node_id_to_monotype(ecx.ccx.tcx, nitem.id));
         encode_symbol(ecx, ebml_w, nitem.id);
       }
diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs
index 9893eb7dde7..1590a8fc095 100644
--- a/src/comp/middle/kind.rs
+++ b/src/comp/middle/kind.rs
@@ -138,6 +138,11 @@ fn check_expr(tcx: &ty::ctxt, e: &@ast::expr) {
       ast::expr_move(a, b) { need_shared_lhs_rhs(tcx, a, b, "<-"); }
       ast::expr_assign(a, b) { need_shared_lhs_rhs(tcx, a, b, "="); }
       ast::expr_swap(a, b) { need_shared_lhs_rhs(tcx, a, b, "<->"); }
+      ast::expr_call(callee, args) {
+        // FIXME: when ready, start checking param kinds against args.
+        // This will break stdlib again.
+        // let tpt = ty::expr_ty_params_and_ty(tcx, callee);
+      }
       _ { }
     }
 }
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index fb981889f7b..5a8efa4f2db 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -296,11 +296,12 @@ fn type_of_arg(cx: @local_ctxt, sp: &span, arg: &ty::arg) -> TypeRef {
     ret typ;
 }
 
-fn type_of_ty_param_count_and_ty(lcx: @local_ctxt, sp: &span,
-                                 tpt: &ty::ty_param_count_and_ty) -> TypeRef {
+fn type_of_ty_param_kinds_and_ty(lcx: @local_ctxt, sp: &span,
+                                 tpt: &ty::ty_param_kinds_and_ty) -> TypeRef {
     alt ty::struct(lcx.ccx.tcx, tpt.ty) {
       ty::ty_fn(_, _, _, _, _) {
-        let llfnty = type_of_fn_from_ty(lcx.ccx, sp, tpt.ty, tpt.count);
+        let llfnty = type_of_fn_from_ty(lcx.ccx, sp, tpt.ty,
+                                        std::ivec::len(tpt.kinds));
         ret T_fn_pair(*lcx.ccx, llfnty);
       }
       _ {
@@ -3970,14 +3971,14 @@ fn lval_val(cx: &@block_ctxt, val: ValueRef) -> lval_result {
 }
 
 fn trans_external_path(cx: &@block_ctxt, did: &ast::def_id,
-                       tpt: &ty::ty_param_count_and_ty) -> ValueRef {
+                       tpt: &ty::ty_param_kinds_and_ty) -> ValueRef {
     let lcx = cx.fcx.lcx;
     let name = csearch::get_symbol(lcx.ccx.sess.get_cstore(), did);
     ret get_extern_const(lcx.ccx.externs, lcx.ccx.llmod, name,
-                         type_of_ty_param_count_and_ty(lcx, cx.sp, tpt));
+                         type_of_ty_param_kinds_and_ty(lcx, cx.sp, tpt));
 }
 
-fn lval_generic_fn(cx: &@block_ctxt, tpt: &ty::ty_param_count_and_ty,
+fn lval_generic_fn(cx: &@block_ctxt, tpt: &ty::ty_param_kinds_and_ty,
                    fn_id: &ast::def_id, id: ast::node_id) -> lval_result {
     let lv;
     if fn_id.crate == ast::local_crate {
@@ -4101,10 +4102,11 @@ fn trans_var(cx: &@block_ctxt, sp: &span, id: ast::node_id) ->
             ret lval_mem(cx, ccx.consts.get(did.node));
         } else {
             let tp = ty::node_id_to_monotype(ccx.tcx, id);
+            let k: ast::kind[] = ~[];
             ret lval_val(cx,
                          load_if_immediate(cx,
                                            trans_external_path(cx, did,
-                                                               {count: 0u,
+                                                               {kinds: k,
                                                                 ty: tp}),
                                            tp));
         }
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 37ca0632cab..c25821b2b63 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -44,6 +44,7 @@ export def_has_ty_params;
 export eq_ty;
 export expr_has_ty_params;
 export expr_ty;
+export expr_ty_params_and_ty;
 export fold_ty;
 export field;
 export field_idx;
@@ -113,7 +114,7 @@ export t;
 export tag_variants;
 export tag_variant_with_id;
 export ty_param_substs_opt_and_ty;
-export ty_param_count_and_ty;
+export ty_param_kinds_and_ty;
 export ty_native_fn;
 export ty_bool;
 export ty_bot;
@@ -304,9 +305,9 @@ tag type_err {
     terr_constr_mismatch(@type_constr, @type_constr);
 }
 
-type ty_param_count_and_ty = {count: uint, ty: t};
+type ty_param_kinds_and_ty = {kinds: ast::kind[], ty: t};
 
-type type_cache = hashmap[ast::def_id, ty_param_count_and_ty];
+type type_cache = hashmap[ast::def_id, ty_param_kinds_and_ty];
 
 const idx_nil: uint = 0u;
 
@@ -400,7 +401,7 @@ fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
            freevars: freevars::freevar_map) -> ctxt {
     let ntt: node_type_table =
         @smallintmap::mk[ty::ty_param_substs_opt_and_ty]();
-    let tcache = new_def_hash[ty::ty_param_count_and_ty]();
+    let tcache = new_def_hash[ty::ty_param_kinds_and_ty]();
     let ts = @interner::mk[@raw_t](hash_raw_ty, eq_raw_ty);
     let cx =
         @{ts: ts,
@@ -2832,7 +2833,7 @@ fn tag_variant_with_id(cx: &ctxt, tag_id: &ast::def_id,
 
 // If the given item is in an external crate, looks up its type and adds it to
 // the type cache. Returns the type parameters and type.
-fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_count_and_ty {
+fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_kinds_and_ty {
     if did.crate == ast::local_crate {
         // The item is in this crate. The caller should have added it to the
         // type cache already; we simply return it.
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index dc32e006287..e6077e2ff0d 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -25,7 +25,7 @@ import middle::ty::node_type_table;
 import middle::ty::pat_ty;
 import middle::ty::ty_param_substs_opt_and_ty;
 import util::ppaux::ty_to_str;
-import middle::ty::ty_param_count_and_ty;
+import middle::ty::ty_param_kinds_and_ty;
 import middle::ty::ty_nil;
 import middle::ty::unify::ures_ok;
 import middle::ty::unify::ures_err;
@@ -78,7 +78,7 @@ type fn_ctxt =
 
 
 // Used for ast_ty_to_ty() below.
-type ty_getter = fn(&ast::def_id) -> ty::ty_param_count_and_ty ;
+type ty_getter = fn(&ast::def_id) -> ty::ty_param_kinds_and_ty ;
 
 fn lookup_local(fcx: &@fn_ctxt, sp: &span, id: ast::node_id) -> int {
     alt fcx.locals.find(id) {
@@ -103,23 +103,24 @@ fn lookup_def(fcx: &@fn_ctxt, sp: &span, id: ast::node_id) -> ast::def {
 }
 
 // Returns the type parameter count and the type for the given definition.
-fn ty_param_count_and_ty_for_def(fcx: &@fn_ctxt, sp: &span, defn: &ast::def)
-   -> ty_param_count_and_ty {
+fn ty_param_kinds_and_ty_for_def(fcx: &@fn_ctxt, sp: &span, defn: &ast::def)
+   -> ty_param_kinds_and_ty {
+    let no_kinds: ast::kind[] = ~[];
     alt defn {
       ast::def_arg(id) {
         assert (fcx.locals.contains_key(id.node));
         let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
-        ret {count: 0u, ty: typ};
+        ret {kinds: no_kinds, ty: typ};
       }
       ast::def_local(id) {
         assert (fcx.locals.contains_key(id.node));
         let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
-        ret {count: 0u, ty: typ};
+        ret {kinds: no_kinds, ty: typ};
       }
       ast::def_obj_field(id) {
         assert (fcx.locals.contains_key(id.node));
         let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
-        ret {count: 0u, ty: typ};
+        ret {kinds: no_kinds, ty: typ};
       }
       ast::def_fn(id, _) { ret ty::lookup_item_type(fcx.ccx.tcx, id); }
       ast::def_native_fn(id) { ret ty::lookup_item_type(fcx.ccx.tcx, id); }
@@ -128,13 +129,13 @@ fn ty_param_count_and_ty_for_def(fcx: &@fn_ctxt, sp: &span, defn: &ast::def)
       ast::def_binding(id) {
         assert (fcx.locals.contains_key(id.node));
         let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
-        ret {count: 0u, ty: typ};
+        ret {kinds: no_kinds, ty: typ};
       }
       ast::def_mod(_) {
         // Hopefully part of a path.
         // TODO: return a type that's more poisonous, perhaps?
 
-        ret {count: 0u, ty: ty::mk_nil(fcx.ccx.tcx)};
+        ret {kinds: no_kinds, ty: ty::mk_nil(fcx.ccx.tcx)};
       }
       ast::def_ty(_) {
         fcx.ccx.tcx.sess.span_fatal(sp, "expected value but found type");
@@ -151,9 +152,9 @@ fn ty_param_count_and_ty_for_def(fcx: &@fn_ctxt, sp: &span, defn: &ast::def)
 // Instantiates the given path, which must refer to an item with the given
 // number of type parameters and type.
 fn instantiate_path(fcx: &@fn_ctxt, pth: &ast::path,
-                    tpt: &ty_param_count_and_ty, sp: &span) ->
+                    tpt: &ty_param_kinds_and_ty, sp: &span) ->
    ty_param_substs_opt_and_ty {
-    let ty_param_count = tpt.count;
+    let ty_param_count = ivec::len(tpt.kinds);
     let bind_result =
         bind_params_in_type(sp, fcx.ccx.tcx, bind next_ty_var_id(fcx), tpt.ty,
                             ty_param_count);
@@ -287,7 +288,9 @@ fn ast_ty_to_ty(tcx: &ty::ctxt, getter: &ty_getter, ast_ty: &@ast::ty) ->
         // "foo = int" like OCaml?
 
         let params_opt_and_ty = getter(id);
-        if params_opt_and_ty.count == 0u { ret params_opt_and_ty.ty; }
+        if ivec::len(params_opt_and_ty.kinds) == 0u {
+            ret params_opt_and_ty.ty;
+        }
         // The typedef is type-parametric. Do the type substitution.
         //
 
@@ -421,7 +424,7 @@ fn ast_ty_to_ty(tcx: &ty::ctxt, getter: &ty_getter, ast_ty: &@ast::ty) ->
 // ast_ty_to_ty.
 fn ast_ty_to_ty_crate(ccx: @crate_ctxt, ast_ty: &@ast::ty) -> ty::t {
     fn getter(ccx: @crate_ctxt, id: &ast::def_id) ->
-       ty::ty_param_count_and_ty {
+       ty::ty_param_kinds_and_ty {
         ret ty::lookup_item_type(ccx.tcx, id);
     }
     let f = bind getter(ccx, _);
@@ -512,11 +515,20 @@ mod collect {
         }
         ret tps;
     }
+
+    fn ty_param_kinds(tps: &ast::ty_param[]) -> ast::kind[] {
+        let k: ast::kind[] = ~[];
+        for p: ast::ty_param in tps {
+            k += ~[p.kind]
+        }
+        ret k;
+    }
+
     fn ty_of_fn_decl(cx: &@ctxt, convert: &fn(&@ast::ty) -> ty::t ,
                      ty_of_arg: &fn(&ast::arg) -> arg , decl: &ast::fn_decl,
                      proto: ast::proto, ty_params: &ast::ty_param[],
                      def_id: &option::t[ast::def_id]) ->
-       ty::ty_param_count_and_ty {
+       ty::ty_param_kinds_and_ty {
         let input_tys = ~[];
         for a: ast::arg  in decl.inputs { input_tys += ~[ty_of_arg(a)]; }
         let output_ty = convert(decl.output);
@@ -528,8 +540,7 @@ mod collect {
         let t_fn =
             ty::mk_fn(cx.tcx, proto_to_ty_proto(proto), input_tys, output_ty,
                       decl.cf, out_constrs);
-        let ty_param_count = ivec::len[ast::ty_param](ty_params);
-        let tpt = {count: ty_param_count, ty: t_fn};
+        let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
         alt def_id { some(did) { cx.tcx.tcache.insert(did, tpt); } _ { } }
         ret tpt;
     }
@@ -537,18 +548,17 @@ mod collect {
                             ty_of_arg: &fn(&ast::arg) -> arg ,
                             decl: &ast::fn_decl, abi: ast::native_abi,
                             ty_params: &ast::ty_param[], def_id: &ast::def_id)
-       -> ty::ty_param_count_and_ty {
+       -> ty::ty_param_kinds_and_ty {
         let input_tys = ~[];
         for a: ast::arg  in decl.inputs { input_tys += ~[ty_of_arg(a)]; }
         let output_ty = convert(decl.output);
 
         let t_fn = ty::mk_native_fn(cx.tcx, abi, input_tys, output_ty);
-        let ty_param_count = ivec::len[ast::ty_param](ty_params);
-        let tpt = {count: ty_param_count, ty: t_fn};
+        let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
         cx.tcx.tcache.insert(def_id, tpt);
         ret tpt;
     }
-    fn getter(cx: @ctxt, id: &ast::def_id) -> ty::ty_param_count_and_ty {
+    fn getter(cx: @ctxt, id: &ast::def_id) -> ty::ty_param_kinds_and_ty {
         if id.crate != ast::local_crate {
             // This is a type we need to load in from the crate reader.
             ret csearch::get_type(cx.tcx, id);
@@ -603,15 +613,15 @@ mod collect {
              constrs: out_constrs};
     }
     fn ty_of_obj(cx: @ctxt, id: &ast::ident, ob: &ast::_obj,
-                 ty_params: &ast::ty_param[]) -> ty::ty_param_count_and_ty {
+                 ty_params: &ast::ty_param[]) -> ty::ty_param_kinds_and_ty {
         let methods = get_obj_method_types(cx, ob);
         let t_obj = ty::mk_obj(cx.tcx, ty::sort_methods(methods));
         t_obj = ty::rename(cx.tcx, t_obj, id);
-        ret {count: ivec::len(ty_params), ty: t_obj};
+        ret {kinds: ty_param_kinds(ty_params), ty: t_obj};
     }
     fn ty_of_obj_ctor(cx: @ctxt, id: &ast::ident, ob: &ast::_obj,
                       ctor_id: ast::node_id, ty_params: &ast::ty_param[]) ->
-       ty::ty_param_count_and_ty {
+       ty::ty_param_kinds_and_ty {
         let t_obj = ty_of_obj(cx, id, ob, ty_params);
 
         let t_inputs: arg[] = ~[];
@@ -624,17 +634,18 @@ mod collect {
         let t_fn =
             ty::mk_fn(cx.tcx, ast::proto_fn, t_inputs, t_obj.ty, ast::return,
                       ~[]);
-        let tpt = {count: t_obj.count, ty: t_fn};
+        let tpt = {kinds: ty_param_kinds(ty_params), ty: t_fn};
         cx.tcx.tcache.insert(local_def(ctor_id), tpt);
         ret tpt;
     }
-    fn ty_of_item(cx: &@ctxt, it: &@ast::item) -> ty::ty_param_count_and_ty {
+    fn ty_of_item(cx: &@ctxt, it: &@ast::item) -> ty::ty_param_kinds_and_ty {
         let get = bind getter(cx, _);
         let convert = bind ast_ty_to_ty(cx.tcx, get, _);
+        let no_kinds: ast::kind[] = ~[];
         alt it.node {
           ast::item_const(t, _) {
             let typ = convert(t);
-            let tpt = {count: 0u, ty: typ};
+            let tpt = {kinds: no_kinds, ty: typ};
             cx.tcx.tcache.insert(local_def(it.id), tpt);
             ret tpt;
           }
@@ -657,15 +668,14 @@ mod collect {
             // call to resolve any named types.
 
             let typ = convert(t);
-            let ty_param_count = ivec::len[ast::ty_param](tps);
-            let tpt = {count: ty_param_count, ty: typ};
+            let tpt = {kinds: ty_param_kinds(tps), ty: typ};
             cx.tcx.tcache.insert(local_def(it.id), tpt);
             ret tpt;
           }
           ast::item_res(f, _, tps, _) {
             let t_arg = ty_of_arg(cx, f.decl.inputs.(0));
             let t_res =
-                {count: ivec::len(tps),
+                {kinds: ty_param_kinds(tps),
                  ty:
                      ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty,
                                 mk_ty_params(cx, tps))};
@@ -674,12 +684,9 @@ mod collect {
           }
           ast::item_tag(_, tps) {
             // Create a new generic polytype.
-
-            let ty_param_count = ivec::len[ast::ty_param](tps);
-
             let subtys: ty::t[] = mk_ty_params(cx, tps);
             let t = ty::mk_tag(cx.tcx, local_def(it.id), subtys);
-            let tpt = {count: ty_param_count, ty: t};
+            let tpt = {kinds: ty_param_kinds(tps), ty: t};
             cx.tcx.tcache.insert(local_def(it.id), tpt);
             ret tpt;
           }
@@ -688,7 +695,8 @@ mod collect {
         }
     }
     fn ty_of_native_item(cx: &@ctxt, it: &@ast::native_item,
-                         abi: ast::native_abi) -> ty::ty_param_count_and_ty {
+                         abi: ast::native_abi) -> ty::ty_param_kinds_and_ty {
+        let no_kinds: ast::kind[] = ~[];
         alt it.node {
           ast::native_item_fn(_, fn_decl, params) {
             let get = bind getter(cx, _);
@@ -703,7 +711,7 @@ mod collect {
               none. { }
             }
             let t = ty::mk_native(cx.tcx, ast::local_def(it.id));
-            let tpt = {count: 0u, ty: t};
+            let tpt = {kinds: no_kinds, ty: t};
             cx.tcx.tcache.insert(local_def(it.id), tpt);
             ret tpt;
           }
@@ -714,7 +722,6 @@ mod collect {
                              ty_params: &ast::ty_param[]) {
         // Create a set of parameter types shared among all the variants.
 
-        let ty_param_count = ivec::len[ast::ty_param](ty_params);
         let ty_param_tys: ty::t[] = mk_ty_params(cx, ty_params);
         for variant: ast::variant  in variants {
             // Nullary tag constructors get turned into constants; n-ary tag
@@ -739,7 +746,7 @@ mod collect {
                     ty::mk_fn(cx.tcx, ast::proto_fn, args, tag_t, ast::return,
                               ~[]);
             }
-            let tpt = {count: ty_param_count, ty: result_ty};
+            let tpt = {kinds: ty_param_kinds(ty_params), ty: result_ty};
             cx.tcx.tcache.insert(local_def(variant.node.id), tpt);
             write::ty_only(cx.tcx, variant.node.id, result_ty);
         }
@@ -819,7 +826,7 @@ mod collect {
             write::ty_only(cx.tcx, it.id, t_res);
             write::ty_only(cx.tcx, ctor_id, t_ctor);
             cx.tcx.tcache.insert(local_def(ctor_id),
-                                 {count: ivec::len(tps), ty: t_ctor});
+                                 {kinds: ty_param_kinds(tps), ty: t_ctor});
             write::ty_only(cx.tcx, dtor_id, t_dtor);
           }
           _ {
@@ -1792,7 +1799,7 @@ fn check_expr(fcx: &@fn_ctxt, expr: &@ast::expr) -> bool {
       }
       ast::expr_path(pth) {
         let defn = lookup_def(fcx, pth.span, id);
-        let tpt = ty_param_count_and_ty_for_def(fcx, expr.span, defn);
+        let tpt = ty_param_kinds_and_ty_for_def(fcx, expr.span, defn);
         if ty::def_has_ty_params(defn) {
             let path_tpot = instantiate_path(fcx, pth, tpt, expr.span);
             write::ty_fixup(fcx, id, path_tpot);