rustc: Switch to indices for type parameters

This commit is contained in:
Patrick Walton 2011-04-12 15:09:50 -07:00
parent e11e8754de
commit de0175abed
9 changed files with 255 additions and 382 deletions

View file

@ -17,7 +17,7 @@ type crate_num = int;
type def_num = int; type def_num = int;
type def_id = tup(crate_num, def_num); type def_id = tup(crate_num, def_num);
type ty_param = rec(ident ident, def_id id); type ty_param = ident;
// Annotations added during successive passes. // Annotations added during successive passes.
tag ann { tag ann {
@ -39,7 +39,7 @@ tag def {
def_upvar(def_id); def_upvar(def_id);
def_variant(def_id /* tag */, def_id /* variant */); def_variant(def_id /* tag */, def_id /* variant */);
def_ty(def_id); def_ty(def_id);
def_ty_arg(def_id); def_ty_arg(uint);
def_binding(def_id); def_binding(def_id);
def_use(def_id); def_use(def_id);
def_native_ty(def_id); def_native_ty(def_id);
@ -59,7 +59,7 @@ fn def_id_of_def(def d) -> def_id {
case (def_upvar(?id)) { ret id; } case (def_upvar(?id)) { ret id; }
case (def_variant(_, ?id)) { ret id; } case (def_variant(_, ?id)) { ret id; }
case (def_ty(?id)) { ret id; } case (def_ty(?id)) { ret id; }
case (def_ty_arg(?id)) { ret id; } case (def_ty_arg(_)) { fail; }
case (def_binding(?id)) { ret id; } case (def_binding(?id)) { ret id; }
case (def_use(?id)) { ret id; } case (def_use(?id)) { ret id; }
case (def_native_ty(?id)) { ret id; } case (def_native_ty(?id)) { ret id; }

View file

@ -131,7 +131,7 @@ impure fn parse_sty(@pstate st, str_def sd) -> ty.sty {
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
ret ty.ty_tag(def, params); ret ty.ty_tag(def, params);
} }
case ('p') {ret ty.ty_param(parse_def(st, sd));} case ('p') {ret ty.ty_param(parse_int(st) as uint);}
case ('@') {ret ty.ty_box(parse_mt(st, sd));} case ('@') {ret ty.ty_box(parse_mt(st, sd));}
case ('V') {ret ty.ty_vec(parse_mt(st, sd));} case ('V') {ret ty.ty_vec(parse_mt(st, sd));}
case ('P') {ret ty.ty_port(parse_ty(st, sd));} case ('P') {ret ty.ty_port(parse_ty(st, sd));}
@ -351,14 +351,13 @@ fn item_type(&ebml.doc item, int this_cnum) -> @ty.t {
ret parse_ty_str(s, bind parse_external_def_id(this_cnum, _)); ret parse_ty_str(s, bind parse_external_def_id(this_cnum, _));
} }
fn item_ty_params(&ebml.doc item, int this_cnum) -> vec[ast.def_id] { fn item_ty_param_count(&ebml.doc item, int this_cnum) -> uint {
let vec[ast.def_id] params = vec(); let uint ty_param_count = 0u;
auto tp = metadata.tag_items_data_item_ty_param; auto tp = metadata.tag_items_data_item_ty_param_count;
for each (ebml.doc p in ebml.tagged_docs(item, tp)) { for each (ebml.doc p in ebml.tagged_docs(item, tp)) {
auto ext = parse_def_id(ebml.doc_data(p)); ty_param_count = ebml.vint_at(ebml.doc_data(p), 0u)._0;
_vec.push[ast.def_id](params, tup(this_cnum, ext._1));
} }
ret params; ret ty_param_count;
} }
fn tag_variant_ids(&ebml.doc item, int this_cnum) -> vec[ast.def_id] { fn tag_variant_ids(&ebml.doc item, int this_cnum) -> vec[ast.def_id] {
@ -511,23 +510,23 @@ fn lookup_def(session.session sess, int cnum, vec[ast.ident] path)
ret some[ast.def](def); ret some[ast.def](def);
} }
fn get_type(session.session sess, ast.def_id def) -> ty.ty_params_opt_and_ty { fn get_type(session.session sess, ast.def_id def)
-> ty.ty_param_count_and_ty {
auto external_crate_id = def._0; auto external_crate_id = def._0;
auto data = sess.get_external_crate(external_crate_id); auto data = sess.get_external_crate(external_crate_id);
auto item = lookup_item(def._1, data); auto item = lookup_item(def._1, data);
auto t = item_type(item, external_crate_id); auto t = item_type(item, external_crate_id);
auto tps_opt; auto tp_count;
auto kind_ch = item_kind(item); auto kind_ch = item_kind(item);
auto has_ty_params = kind_has_type_params(kind_ch); auto has_ty_params = kind_has_type_params(kind_ch);
if (has_ty_params) { if (has_ty_params) {
auto tps = item_ty_params(item, external_crate_id); tp_count = item_ty_param_count(item, external_crate_id);
tps_opt = some[vec[ast.def_id]](tps);
} else { } else {
tps_opt = none[vec[ast.def_id]]; tp_count = 0u;
} }
ret tup(tps_opt, t); ret tup(tp_count, t);
} }
fn get_symbol(session.session sess, ast.def_id def) -> str { fn get_symbol(session.session sess, ast.def_id def) -> str {

View file

@ -1740,8 +1740,7 @@ impure fn parse_block(parser p) -> ast.block {
} }
impure fn parse_ty_param(parser p) -> ast.ty_param { impure fn parse_ty_param(parser p) -> ast.ty_param {
auto ident = parse_ident(p); ret parse_ident(p);
ret rec(ident=ident, id=p.next_def_id());
} }
impure fn parse_ty_params(parser p) -> vec[ast.ty_param] { impure fn parse_ty_params(parser p) -> vec[ast.ty_param] {

View file

@ -29,7 +29,7 @@ const uint tag_def_id = 0x07u;
const uint tag_items_data = 0x08u; const uint tag_items_data = 0x08u;
const uint tag_items_data_item = 0x09u; const uint tag_items_data_item = 0x09u;
const uint tag_items_data_item_kind = 0x0au; const uint tag_items_data_item_kind = 0x0au;
const uint tag_items_data_item_ty_param = 0x0bu; const uint tag_items_data_item_ty_param_count = 0x0bu;
const uint tag_items_data_item_type = 0x0cu; const uint tag_items_data_item_type = 0x0cu;
const uint tag_items_data_item_symbol = 0x0du; const uint tag_items_data_item_symbol = 0x0du;
const uint tag_items_data_item_variant = 0x0eu; const uint tag_items_data_item_variant = 0x0eu;
@ -134,7 +134,7 @@ fn sty_str(ty.sty st, def_str ds) -> str {
} }
case (ty.ty_var(?id)) {ret "X" + common.istr(id);} case (ty.ty_var(?id)) {ret "X" + common.istr(id);}
case (ty.ty_native) {ret "E";} case (ty.ty_native) {ret "E";}
case (ty.ty_param(?def)) {ret "p" + ds(def) + "|";} case (ty.ty_param(?id)) {ret "p" + common.uistr(id);}
case (ty.ty_type) {ret "Y";} case (ty.ty_type) {ret "Y";}
} }
} }
@ -310,13 +310,10 @@ fn def_to_str(ast.def_id did) -> str {
ret #fmt("%d:%d", did._0, did._1); ret #fmt("%d:%d", did._0, did._1);
} }
// TODO: We need to encode the "crate numbers" somewhere for diamond imports. fn encode_type_param_count(&ebml.writer ebml_w, vec[ast.ty_param] tps) {
fn encode_type_params(&ebml.writer ebml_w, vec[ast.ty_param] tps) { ebml.start_tag(ebml_w, tag_items_data_item_ty_param_count);
for (ast.ty_param tp in tps) { ebml.write_vint(ebml_w.writer, _vec.len[ast.ty_param](tps));
ebml.start_tag(ebml_w, tag_items_data_item_ty_param);
ebml_w.writer.write(_str.bytes(def_to_str(tp.id)));
ebml.end_tag(ebml_w); ebml.end_tag(ebml_w);
}
} }
fn encode_variant_id(&ebml.writer ebml_w, ast.def_id vid) { fn encode_variant_id(&ebml.writer ebml_w, ast.def_id vid) {
@ -374,7 +371,7 @@ fn encode_tag_variant_info(@trans.crate_ctxt cx, &ebml.writer ebml_w,
encode_symbol(cx, ebml_w, variant.node.id); encode_symbol(cx, ebml_w, variant.node.id);
} }
encode_discriminant(cx, ebml_w, variant.node.id); encode_discriminant(cx, ebml_w, variant.node.id);
encode_type_params(ebml_w, ty_params); encode_type_param_count(ebml_w, ty_params);
ebml.end_tag(ebml_w); ebml.end_tag(ebml_w);
} }
} }
@ -394,7 +391,7 @@ fn encode_info_for_item(@trans.crate_ctxt cx, &ebml.writer ebml_w,
ebml.start_tag(ebml_w, tag_items_data_item); ebml.start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, did); encode_def_id(ebml_w, did);
encode_kind(ebml_w, 'f' as u8); encode_kind(ebml_w, 'f' as u8);
encode_type_params(ebml_w, tps); encode_type_param_count(ebml_w, tps);
encode_type(ebml_w, trans.node_ann_type(cx, ann)); encode_type(ebml_w, trans.node_ann_type(cx, ann));
encode_symbol(cx, ebml_w, did); encode_symbol(cx, ebml_w, did);
ebml.end_tag(ebml_w); ebml.end_tag(ebml_w);
@ -415,7 +412,7 @@ fn encode_info_for_item(@trans.crate_ctxt cx, &ebml.writer ebml_w,
ebml.start_tag(ebml_w, tag_items_data_item); ebml.start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, did); encode_def_id(ebml_w, did);
encode_kind(ebml_w, 'y' as u8); encode_kind(ebml_w, 'y' as u8);
encode_type_params(ebml_w, tps); encode_type_param_count(ebml_w, tps);
encode_type(ebml_w, trans.node_ann_type(cx, ann)); encode_type(ebml_w, trans.node_ann_type(cx, ann));
ebml.end_tag(ebml_w); ebml.end_tag(ebml_w);
} }
@ -423,7 +420,7 @@ fn encode_info_for_item(@trans.crate_ctxt cx, &ebml.writer ebml_w,
ebml.start_tag(ebml_w, tag_items_data_item); ebml.start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, did); encode_def_id(ebml_w, did);
encode_kind(ebml_w, 't' as u8); encode_kind(ebml_w, 't' as u8);
encode_type_params(ebml_w, tps); encode_type_param_count(ebml_w, tps);
encode_type(ebml_w, trans.node_ann_type(cx, ann)); encode_type(ebml_w, trans.node_ann_type(cx, ann));
for (ast.variant v in variants) { for (ast.variant v in variants) {
encode_variant_id(ebml_w, v.node.id); encode_variant_id(ebml_w, v.node.id);
@ -436,7 +433,7 @@ fn encode_info_for_item(@trans.crate_ctxt cx, &ebml.writer ebml_w,
ebml.start_tag(ebml_w, tag_items_data_item); ebml.start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, odid.ctor); encode_def_id(ebml_w, odid.ctor);
encode_kind(ebml_w, 'o' as u8); encode_kind(ebml_w, 'o' as u8);
encode_type_params(ebml_w, tps); encode_type_param_count(ebml_w, tps);
auto fn_ty = trans.node_ann_type(cx, ann); auto fn_ty = trans.node_ann_type(cx, ann);
encode_type(ebml_w, fn_ty); encode_type(ebml_w, fn_ty);
encode_symbol(cx, ebml_w, odid.ctor); encode_symbol(cx, ebml_w, odid.ctor);
@ -445,7 +442,7 @@ fn encode_info_for_item(@trans.crate_ctxt cx, &ebml.writer ebml_w,
ebml.start_tag(ebml_w, tag_items_data_item); ebml.start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, odid.ty); encode_def_id(ebml_w, odid.ty);
encode_kind(ebml_w, 'y' as u8); encode_kind(ebml_w, 'y' as u8);
encode_type_params(ebml_w, tps); encode_type_param_count(ebml_w, tps);
encode_type(ebml_w, ty.ty_fn_ret(fn_ty)); encode_type(ebml_w, ty.ty_fn_ret(fn_ty));
ebml.end_tag(ebml_w); ebml.end_tag(ebml_w);
} }
@ -464,7 +461,7 @@ fn encode_info_for_native_item(@trans.crate_ctxt cx, &ebml.writer ebml_w,
case (ast.native_item_fn(_, _, _, ?tps, ?did, ?ann)) { case (ast.native_item_fn(_, _, _, ?tps, ?did, ?ann)) {
encode_def_id(ebml_w, did); encode_def_id(ebml_w, did);
encode_kind(ebml_w, 'F' as u8); encode_kind(ebml_w, 'F' as u8);
encode_type_params(ebml_w, tps); encode_type_param_count(ebml_w, tps);
encode_type(ebml_w, trans.node_ann_type(cx, ann)); encode_type(ebml_w, trans.node_ann_type(cx, ann));
encode_symbol(cx, ebml_w, did); encode_symbol(cx, ebml_w, did);
} }

View file

@ -398,19 +398,22 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
} }
} }
fn handle_fn_decl(ast.ident i, &ast.fn_decl decl, fn handle_fn_decl(ast.ident identifier, &ast.fn_decl decl,
&vec[ast.ty_param] ty_params) -> option.t[def_wrap] { &vec[ast.ty_param] ty_params) -> option.t[def_wrap] {
for (ast.arg a in decl.inputs) { for (ast.arg a in decl.inputs) {
if (_str.eq(a.ident, i)) { if (_str.eq(a.ident, identifier)) {
auto t = ast.def_arg(a.id); auto t = ast.def_arg(a.id);
ret some(def_wrap_other(t)); ret some(def_wrap_other(t));
} }
} }
auto i = 0u;
for (ast.ty_param tp in ty_params) { for (ast.ty_param tp in ty_params) {
if (_str.eq(tp.ident, i)) { if (_str.eq(tp, identifier)) {
auto t = ast.def_ty_arg(tp.id); auto t = ast.def_ty_arg(i);
ret some(def_wrap_other(t)); ret some(def_wrap_other(t));
} }
i += 1u;
} }
ret none[def_wrap]; ret none[def_wrap];
} }
@ -450,53 +453,60 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
} }
} }
fn in_scope(&session.session sess, ast.ident i, &scope s, namespace ns) fn in_scope(&session.session sess, ast.ident identifier, &scope s,
-> option.t[def_wrap] { namespace ns) -> option.t[def_wrap] {
alt (s) { alt (s) {
case (scope_crate(?c)) { case (scope_crate(?c)) {
ret check_mod(i, c.node.module, ns); ret check_mod(identifier, c.node.module, ns);
} }
case (scope_item(?it)) { case (scope_item(?it)) {
alt (it.node) { alt (it.node) {
case (ast.item_fn(_, ?f, ?ty_params, _, _)) { case (ast.item_fn(_, ?f, ?ty_params, _, _)) {
ret handle_fn_decl(i, f.decl, ty_params); ret handle_fn_decl(identifier, f.decl, ty_params);
} }
case (ast.item_obj(_, ?ob, ?ty_params, _, _)) { case (ast.item_obj(_, ?ob, ?ty_params, _, _)) {
for (ast.obj_field f in ob.fields) { for (ast.obj_field f in ob.fields) {
if (_str.eq(f.ident, i)) { if (_str.eq(f.ident, identifier)) {
auto t = ast.def_obj_field(f.id); auto t = ast.def_obj_field(f.id);
ret some(def_wrap_other(t)); ret some(def_wrap_other(t));
} }
} }
auto i = 0u;
for (ast.ty_param tp in ty_params) { for (ast.ty_param tp in ty_params) {
if (_str.eq(tp.ident, i)) { if (_str.eq(tp, identifier)) {
auto t = ast.def_ty_arg(tp.id); auto t = ast.def_ty_arg(i);
ret some(def_wrap_other(t)); ret some(def_wrap_other(t));
} }
i += 1u;
} }
} }
case (ast.item_tag(_,?variants,?ty_params,?tag_id,_)) { case (ast.item_tag(_,?variants,?ty_params,?tag_id,_)) {
auto i = 0u;
for (ast.ty_param tp in ty_params) { for (ast.ty_param tp in ty_params) {
if (_str.eq(tp.ident, i)) { if (_str.eq(tp, identifier)) {
auto t = ast.def_ty_arg(tp.id); auto t = ast.def_ty_arg(i);
ret some(def_wrap_other(t)); ret some(def_wrap_other(t));
} }
i += 1u;
} }
} }
case (ast.item_mod(_, ?m, _)) { case (ast.item_mod(_, ?m, _)) {
ret check_mod(i, m, ns); ret check_mod(identifier, m, ns);
} }
case (ast.item_native_mod(_, ?m, _)) { case (ast.item_native_mod(_, ?m, _)) {
ret check_native_mod(i, m); ret check_native_mod(identifier, m);
} }
case (ast.item_ty(_, _, ?ty_params, _, _)) { case (ast.item_ty(_, _, ?ty_params, _, _)) {
auto i = 0u;
for (ast.ty_param tp in ty_params) { for (ast.ty_param tp in ty_params) {
if (_str.eq(tp.ident, i)) { if (_str.eq(tp, identifier)) {
auto t = ast.def_ty_arg(tp.id); auto t = ast.def_ty_arg(i);
ret some(def_wrap_other(t)); ret some(def_wrap_other(t));
} }
i += 1u;
} }
} }
case (_) { /* fall through */ } case (_) { /* fall through */ }
@ -506,7 +516,7 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
case (scope_native_item(?it)) { case (scope_native_item(?it)) {
alt (it.node) { alt (it.node) {
case (ast.native_item_fn(_, _, ?decl, ?ty_params, _, _)) { case (ast.native_item_fn(_, _, ?decl, ?ty_params, _, _)) {
ret handle_fn_decl(i, decl, ty_params); ret handle_fn_decl(identifier, decl, ty_params);
} }
} }
} }
@ -518,7 +528,7 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
case (scope_loop(?d)) { case (scope_loop(?d)) {
alt (d.node) { alt (d.node) {
case (ast.decl_local(?local)) { case (ast.decl_local(?local)) {
if (_str.eq(local.ident, i)) { if (_str.eq(local.ident, identifier)) {
auto lc = ast.def_local(local.id); auto lc = ast.def_local(local.id);
ret some(def_wrap_other(lc)); ret some(def_wrap_other(lc));
} }
@ -527,11 +537,11 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
} }
case (scope_block(?b)) { case (scope_block(?b)) {
ret check_block(i, b.node, ns); ret check_block(identifier, b.node, ns);
} }
case (scope_arm(?a)) { case (scope_arm(?a)) {
alt (a.index.find(i)) { alt (a.index.find(identifier)) {
case (some[ast.def_id](?did)) { case (some[ast.def_id](?did)) {
auto t = ast.def_binding(did); auto t = ast.def_binding(did);
ret some[def_wrap](def_wrap_other(t)); ret some[def_wrap](def_wrap_other(t));

View file

@ -128,7 +128,8 @@ state type fn_ctxt = rec(ValueRef llfn,
hashmap[ast.def_id, ValueRef] llobjfields, hashmap[ast.def_id, ValueRef] llobjfields,
hashmap[ast.def_id, ValueRef] lllocals, hashmap[ast.def_id, ValueRef] lllocals,
hashmap[ast.def_id, ValueRef] llupvars, hashmap[ast.def_id, ValueRef] llupvars,
hashmap[ast.def_id, ValueRef] lltydescs, // FIXME: this should probably be just vec[ValueRef]
hashmap[uint, ValueRef] lltydescs,
@crate_ctxt ccx); @crate_ctxt ccx);
tag cleanup { tag cleanup {
@ -770,14 +771,11 @@ fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef {
ret typ; ret typ;
} }
fn type_of_ty_params_opt_and_ty(@crate_ctxt ccx, ty.ty_params_opt_and_ty tpt) fn type_of_ty_param_count_and_ty(@crate_ctxt ccx,
-> TypeRef { ty.ty_param_count_and_ty tpt) -> TypeRef {
alt (tpt._1.struct) { alt (tpt._1.struct) {
case (ty.ty_fn(?proto, ?inputs, ?output)) { case (ty.ty_fn(?proto, ?inputs, ?output)) {
auto ty_params = option.get[vec[ast.def_id]](tpt._0); auto llfnty = type_of_fn(ccx, proto, inputs, output, tpt._0);
auto ty_param_count = _vec.len[ast.def_id](ty_params);
auto llfnty = type_of_fn(ccx, proto, inputs, output,
ty_param_count);
ret T_fn_pair(ccx.tn, llfnty); ret T_fn_pair(ccx.tn, llfnty);
} }
case (_) { case (_) {
@ -1121,9 +1119,6 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint {
} }
} }
// Pull the type parameters out of the corresponding tag item.
let vec[ast.def_id] ty_params = tag_ty_params(cx, tid);
// Compute max(variant sizes). // Compute max(variant sizes).
auto max_size = 0u; auto max_size = 0u;
auto variants = tag_variants(cx, tid); auto variants = tag_variants(cx, tid);
@ -1149,7 +1144,7 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint {
auto tup_ty = ty.plain_tup_ty(args); auto tup_ty = ty.plain_tup_ty(args);
// Perform any type parameter substitutions. // Perform any type parameter substitutions.
tup_ty = ty.substitute_ty_params(ty_params, subtys, tup_ty); tup_ty = ty.substitute_type_params(subtys, tup_ty);
// Here we possibly do a recursive call. // Here we possibly do a recursive call.
auto this_size = llsize_of_real(cx, type_of(cx, tup_ty)); auto this_size = llsize_of_real(cx, type_of(cx, tup_ty));
@ -1215,14 +1210,13 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result {
let ValueRef max_size = alloca(bcx, T_int()); let ValueRef max_size = alloca(bcx, T_int());
bcx.build.Store(C_int(0), max_size); bcx.build.Store(C_int(0), max_size);
auto ty_params = tag_ty_params(bcx.fcx.ccx, tid);
auto variants = tag_variants(bcx.fcx.ccx, tid); auto variants = tag_variants(bcx.fcx.ccx, tid);
for (variant_info variant in variants) { for (variant_info variant in variants) {
// Perform type substitution on the raw argument types. // Perform type substitution on the raw argument types.
let vec[@ty.t] raw_tys = variant.args; let vec[@ty.t] raw_tys = variant.args;
let vec[@ty.t] tys = vec(); let vec[@ty.t] tys = vec();
for (@ty.t raw_ty in raw_tys) { for (@ty.t raw_ty in raw_tys) {
auto t = ty.substitute_ty_params(ty_params, tps, raw_ty); auto t = ty.substitute_type_params(tps, raw_ty);
tys += vec(t); tys += vec(t);
} }
@ -1387,7 +1381,6 @@ fn GEP_tag(@block_ctxt cx,
vec[@ty.t] ty_substs, vec[@ty.t] ty_substs,
int ix) int ix)
-> result { -> result {
auto ty_params = tag_ty_params(cx.fcx.ccx, tag_id);
auto variant = tag_variant_with_id(cx.fcx.ccx, tag_id, variant_id); auto variant = tag_variant_with_id(cx.fcx.ccx, tag_id, variant_id);
// Synthesize a tuple type so that GEP_tup_like() can work its magic. // Synthesize a tuple type so that GEP_tup_like() can work its magic.
@ -1397,7 +1390,7 @@ fn GEP_tag(@block_ctxt cx,
auto i = 0; auto i = 0;
let vec[@ty.t] true_arg_tys = vec(); let vec[@ty.t] true_arg_tys = vec();
for (@ty.t aty in arg_tys) { for (@ty.t aty in arg_tys) {
auto arg_ty = ty.substitute_ty_params(ty_params, ty_substs, aty); auto arg_ty = ty.substitute_type_params(ty_substs, aty);
true_arg_tys += vec(arg_ty); true_arg_tys += vec(arg_ty);
if (i == ix) { if (i == ix) {
elem_ty = arg_ty; elem_ty = arg_ty;
@ -1466,23 +1459,23 @@ fn field_of_tydesc(@block_ctxt cx, @ty.t t, int field) -> result {
} }
// Given a type containing ty params, build a vector containing a ValueRef for // Given a type containing ty params, build a vector containing a ValueRef for
// each of the ty params it uses (from the current frame), as well as a vec // each of the ty params it uses (from the current frame) and a vector of the
// containing a def_id for each such param. This is used solely for // indices of the ty params present in the type. This is used solely for
// constructing derived tydescs. // constructing derived tydescs.
fn linearize_ty_params(@block_ctxt cx, @ty.t t) fn linearize_ty_params(@block_ctxt cx, @ty.t t) ->
-> tup(vec[ast.def_id], vec[ValueRef]) { tup(vec[uint], vec[ValueRef]) {
let vec[ValueRef] param_vals = vec(); let vec[ValueRef] param_vals = vec();
let vec[ast.def_id] param_defs = vec(); let vec[uint] param_defs = vec();
type rr = rec(@block_ctxt cx, type rr = rec(@block_ctxt cx,
mutable vec[ValueRef] vals, mutable vec[ValueRef] vals,
mutable vec[ast.def_id] defs); mutable vec[uint] defs);
state obj folder(@rr r) { state obj folder(@rr r) {
fn fold_simple_ty(@ty.t t) -> @ty.t { fn fold_simple_ty(@ty.t t) -> @ty.t {
alt(t.struct) { alt(t.struct) {
case (ty.ty_param(?pid)) { case (ty.ty_param(?pid)) {
let bool seen = false; let bool seen = false;
for (ast.def_id d in r.defs) { for (uint d in r.defs) {
if (d == pid) { if (d == pid) {
seen = true; seen = true;
} }
@ -1511,11 +1504,11 @@ fn linearize_ty_params(@block_ctxt cx, @ty.t t)
fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result {
// Is the supplied type a type param? If so, return the passed-in tydesc. // Is the supplied type a type param? If so, return the passed-in tydesc.
alt (ty.type_param(t)) { alt (ty.type_param(t)) {
case (some[ast.def_id](?id)) { case (some[uint](?id)) {
check (cx.fcx.lltydescs.contains_key(id)); check (cx.fcx.lltydescs.contains_key(id));
ret res(cx, cx.fcx.lltydescs.get(id)); ret res(cx, cx.fcx.lltydescs.get(id));
} }
case (none[ast.def_id]) { /* fall through */ } case (none[uint]) { /* fall through */ }
} }
// Does it contain a type param? If so, generate a derived tydesc. // Does it contain a type param? If so, generate a derived tydesc.
@ -1524,7 +1517,7 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result {
if (ty.count_ty_params(t) > 0u) { if (ty.count_ty_params(t) > 0u) {
auto tys = linearize_ty_params(cx, t); auto tys = linearize_ty_params(cx, t);
check (n_params == _vec.len[ast.def_id](tys._0)); check (n_params == _vec.len[uint](tys._0));
check (n_params == _vec.len[ValueRef](tys._1)); check (n_params == _vec.len[ValueRef](tys._1));
if (!cx.fcx.ccx.tydescs.contains_key(t)) { if (!cx.fcx.ccx.tydescs.contains_key(t)) {
@ -1566,9 +1559,9 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result {
// Otherwise, generate a tydesc if necessary, and return it. // Otherwise, generate a tydesc if necessary, and return it.
if (!cx.fcx.ccx.tydescs.contains_key(t)) { if (!cx.fcx.ccx.tydescs.contains_key(t)) {
let vec[ast.def_id] defs = vec(); let vec[uint] tps = vec();
declare_tydesc(cx.fcx.ccx, t); declare_tydesc(cx.fcx.ccx, t);
define_tydesc(cx.fcx.ccx, t, defs); define_tydesc(cx.fcx.ccx, t, tps);
} }
ret res(cx, cx.fcx.ccx.tydescs.get(t).tydesc); ret res(cx, cx.fcx.ccx.tydescs.get(t).tydesc);
} }
@ -1624,16 +1617,14 @@ fn declare_tydesc(@crate_ctxt cx, @ty.t t) {
} }
// declare_tydesc() above must have been called first. // declare_tydesc() above must have been called first.
fn define_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { fn define_tydesc(@crate_ctxt cx, @ty.t t, vec[uint] ty_params) {
auto info = cx.tydescs.get(t); auto info = cx.tydescs.get(t);
auto gvar = info.tydesc; auto gvar = info.tydesc;
auto tg = make_take_glue; auto tg = make_take_glue;
auto take_glue = make_generic_glue(cx, t, info.take_glue, tg, auto take_glue = make_generic_glue(cx, t, info.take_glue, tg, ty_params);
typaram_defs);
auto dg = make_drop_glue; auto dg = make_drop_glue;
auto drop_glue = make_generic_glue(cx, t, info.drop_glue, dg, auto drop_glue = make_generic_glue(cx, t, info.drop_glue, dg, ty_params);
typaram_defs);
} }
fn declare_generic_glue(@crate_ctxt cx, @ty.t t, str name) -> ValueRef { fn declare_generic_glue(@crate_ctxt cx, @ty.t t, str name) -> ValueRef {
@ -1647,8 +1638,7 @@ fn declare_generic_glue(@crate_ctxt cx, @ty.t t, str name) -> ValueRef {
} }
fn make_generic_glue(@crate_ctxt cx, @ty.t t, ValueRef llfn, fn make_generic_glue(@crate_ctxt cx, @ty.t t, ValueRef llfn,
val_and_ty_fn helper, val_and_ty_fn helper, vec[uint] ty_params) -> ValueRef {
vec[ast.def_id] typaram_defs) -> ValueRef {
auto fcx = new_fn_ctxt(cx, llfn); auto fcx = new_fn_ctxt(cx, llfn);
auto bcx = new_top_block_ctxt(fcx); auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb; auto lltop = bcx.llbb;
@ -1668,13 +1658,15 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, ValueRef llfn,
llty = T_ptr(type_of(cx, t)); llty = T_ptr(type_of(cx, t));
} }
auto ty_param_count = _vec.len[uint](ty_params);
auto lltyparams = llvm.LLVMGetParam(llfn, 3u); auto lltyparams = llvm.LLVMGetParam(llfn, 3u);
auto p = 0; auto p = 0u;
for (ast.def_id d in typaram_defs) { while (p < ty_param_count) {
auto llparam = bcx.build.GEP(lltyparams, vec(C_int(p))); auto llparam = bcx.build.GEP(lltyparams, vec(C_int(p as int)));
llparam = bcx.build.Load(llparam); llparam = bcx.build.Load(llparam);
bcx.fcx.lltydescs.insert(d, llparam); bcx.fcx.lltydescs.insert(ty_params.(p), llparam);
p += 1; p += 1u;
} }
auto llrawptr = llvm.LLVMGetParam(llfn, 4u); auto llrawptr = llvm.LLVMGetParam(llfn, 4u);
@ -1928,11 +1920,6 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx,
// Tag information // Tag information
// Returns the type parameters of a tag.
fn tag_ty_params(@crate_ctxt cx, ast.def_id id) -> vec[ast.def_id] {
ret ty.lookup_generic_item_type(cx.sess, cx.type_cache, id)._0;
}
type variant_info = rec(vec[@ty.t] args, @ty.t ctor_ty, ast.def_id id); type variant_info = rec(vec[@ty.t] args, @ty.t ctor_ty, ast.def_id id);
// Returns information about the variants in a tag. // Returns information about the variants in a tag.
@ -2105,8 +2092,6 @@ fn iter_structural_ty_full(@block_ctxt cx,
auto next_cx = new_sub_block_ctxt(bcx, "tag-iter-next"); auto next_cx = new_sub_block_ctxt(bcx, "tag-iter-next");
auto ty_params = tag_ty_params(bcx.fcx.ccx, tid);
auto i = 0u; auto i = 0u;
for (variant_info variant in variants) { for (variant_info variant in variants) {
auto variant_cx = new_sub_block_ctxt(bcx, auto variant_cx = new_sub_block_ctxt(bcx,
@ -2133,8 +2118,8 @@ fn iter_structural_ty_full(@block_ctxt cx,
auto llfldp_b = rslt.val; auto llfldp_b = rslt.val;
variant_cx = rslt.bcx; variant_cx = rslt.bcx;
auto ty_subst = ty.substitute_ty_params( auto ty_subst =
ty_params, tps, a.ty); ty.substitute_type_params(tps, a.ty);
auto llfld_a = auto llfld_a =
load_if_immediate(variant_cx, load_if_immediate(variant_cx,
@ -3642,16 +3627,16 @@ fn lval_val(@block_ctxt cx, ValueRef val) -> lval_result {
} }
fn trans_external_path(@block_ctxt cx, ast.def_id did, fn trans_external_path(@block_ctxt cx, ast.def_id did,
ty.ty_params_opt_and_ty tpt) -> lval_result { ty.ty_param_count_and_ty tpt) -> lval_result {
auto ccx = cx.fcx.ccx; auto ccx = cx.fcx.ccx;
auto name = creader.get_symbol(ccx.sess, did); auto name = creader.get_symbol(ccx.sess, did);
auto v = get_extern_const(ccx.externs, ccx.llmod, auto v = get_extern_const(ccx.externs, ccx.llmod,
name, type_of_ty_params_opt_and_ty(ccx, tpt)); name, type_of_ty_param_count_and_ty(ccx, tpt));
ret lval_val(cx, v); ret lval_val(cx, v);
} }
fn lval_generic_fn(@block_ctxt cx, fn lval_generic_fn(@block_ctxt cx,
ty.ty_params_and_ty tpt, ty.ty_param_count_and_ty tpt,
ast.def_id fn_id, ast.def_id fn_id,
&ast.ann ann) &ast.ann ann)
-> lval_result { -> lval_result {
@ -3662,12 +3647,11 @@ fn lval_generic_fn(@block_ctxt cx,
lv = lval_val(cx, cx.fcx.ccx.fn_pairs.get(fn_id)); lv = lval_val(cx, cx.fcx.ccx.fn_pairs.get(fn_id));
} else { } else {
// External reference. // External reference.
auto tpot = tup(some[vec[ast.def_id]](tpt._0), tpt._1); lv = trans_external_path(cx, fn_id, tpt);
lv = trans_external_path(cx, fn_id, tpot);
} }
auto monoty; auto monoty;
auto tys; let vec[@ty.t] tys;
alt (ann) { alt (ann) {
case (ast.ann_none) { case (ast.ann_none) {
cx.fcx.ccx.sess.bug("no type annotation for path!"); cx.fcx.ccx.sess.bug("no type annotation for path!");
@ -3750,17 +3734,17 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
ret lval_mem(cx, cx.fcx.llobjfields.get(did)); ret lval_mem(cx, cx.fcx.llobjfields.get(did));
} }
case (ast.def_fn(?did)) { case (ast.def_fn(?did)) {
auto tyt = ty.lookup_generic_item_type(cx.fcx.ccx.sess, auto tyt = ty.lookup_item_type(cx.fcx.ccx.sess,
cx.fcx.ccx.type_cache, did); cx.fcx.ccx.type_cache, did);
ret lval_generic_fn(cx, tyt, did, ann); ret lval_generic_fn(cx, tyt, did, ann);
} }
case (ast.def_obj(?did)) { case (ast.def_obj(?did)) {
auto tyt = ty.lookup_generic_item_type(cx.fcx.ccx.sess, auto tyt = ty.lookup_item_type(cx.fcx.ccx.sess,
cx.fcx.ccx.type_cache, did); cx.fcx.ccx.type_cache, did);
ret lval_generic_fn(cx, tyt, did, ann); ret lval_generic_fn(cx, tyt, did, ann);
} }
case (ast.def_variant(?tid, ?vid)) { case (ast.def_variant(?tid, ?vid)) {
auto v_tyt = ty.lookup_generic_item_type(cx.fcx.ccx.sess, auto v_tyt = ty.lookup_item_type(cx.fcx.ccx.sess,
cx.fcx.ccx.type_cache, vid); cx.fcx.ccx.type_cache, vid);
alt (v_tyt._1.struct) { alt (v_tyt._1.struct) {
case (ty.ty_fn(_, _, _)) { case (ty.ty_fn(_, _, _)) {
@ -3801,7 +3785,7 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
ret lval_mem(cx, cx.fcx.ccx.consts.get(did)); ret lval_mem(cx, cx.fcx.ccx.consts.get(did));
} }
case (ast.def_native_fn(?did)) { case (ast.def_native_fn(?did)) {
auto tyt = ty.lookup_generic_item_type(cx.fcx.ccx.sess, auto tyt = ty.lookup_item_type(cx.fcx.ccx.sess,
cx.fcx.ccx.type_cache, did); cx.fcx.ccx.type_cache, did);
ret lval_generic_fn(cx, tyt, did, ann); ret lval_generic_fn(cx, tyt, did, ann);
} }
@ -5500,7 +5484,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
let hashmap[ast.def_id, ValueRef] llobjfields = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] llobjfields = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] llupvars = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] llupvars = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] lltydescs = new_def_hash[ValueRef](); let hashmap[uint, ValueRef] lltydescs = common.new_uint_hash[ValueRef]();
let BasicBlockRef llallocas = let BasicBlockRef llallocas =
llvm.LLVMAppendBasicBlock(llfndecl, _str.buf("allocas")); llvm.LLVMAppendBasicBlock(llfndecl, _str.buf("allocas"));
@ -5541,11 +5525,13 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx,
cx.llself = some[self_vt](rec(v = cx.llenv, t = tt._1)); cx.llself = some[self_vt](rec(v = cx.llenv, t = tt._1));
} }
case (none[tup(TypeRef, @ty.t)]) { case (none[tup(TypeRef, @ty.t)]) {
auto i = 0u;
for (ast.ty_param tp in ty_params) { for (ast.ty_param tp in ty_params) {
auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n);
check (llarg as int != 0); check (llarg as int != 0);
cx.lltydescs.insert(tp.id, llarg); cx.lltydescs.insert(i, llarg);
arg_n += 1u; arg_n += 1u;
i += 1u;
} }
} }
} }
@ -5695,7 +5681,7 @@ fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, self_vt llself) {
vec(C_int(0), vec(C_int(0),
C_int(i))); C_int(i)));
lltyparam = bcx.build.Load(lltyparam); lltyparam = bcx.build.Load(lltyparam);
fcx.lltydescs.insert(p.id, lltyparam); fcx.lltydescs.insert(i as uint, lltyparam);
i += 1; i += 1;
} }
@ -5889,7 +5875,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
bcx = body_typarams.bcx; bcx = body_typarams.bcx;
let int i = 0; let int i = 0;
for (ast.ty_param tp in ty_params) { for (ast.ty_param tp in ty_params) {
auto typaram = bcx.fcx.lltydescs.get(tp.id); auto typaram = bcx.fcx.lltydescs.get(i as uint);
auto capture = GEP_tup_like(bcx, typarams_ty, body_typarams.val, auto capture = GEP_tup_like(bcx, typarams_ty, body_typarams.val,
vec(0, i)); vec(0, i));
bcx = capture.bcx; bcx = capture.bcx;
@ -5951,8 +5937,10 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
fn_args, ty_params); fn_args, ty_params);
let vec[@ty.t] ty_param_substs = vec(); let vec[@ty.t] ty_param_substs = vec();
i = 0u;
for (ast.ty_param tp in ty_params) { for (ast.ty_param tp in ty_params) {
ty_param_substs += vec(plain_ty(ty.ty_param(tp.id))); ty_param_substs += vec(plain_ty(ty.ty_param(i)));
i += 1u;
} }
auto arg_tys = arg_tys_of_fn(variant.node.ann); auto arg_tys = arg_tys_of_fn(variant.node.ann);
@ -6905,7 +6893,7 @@ fn trans_vec_append_glue(@crate_ctxt cx) {
llobjfields=new_def_hash[ValueRef](), llobjfields=new_def_hash[ValueRef](),
lllocals=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](),
llupvars=new_def_hash[ValueRef](), llupvars=new_def_hash[ValueRef](),
lltydescs=new_def_hash[ValueRef](), lltydescs=common.new_uint_hash[ValueRef](),
ccx=cx); ccx=cx);
auto bcx = new_top_block_ctxt(fcx); auto bcx = new_top_block_ctxt(fcx);

View file

@ -57,7 +57,7 @@ tag sty {
ty_obj(vec[method]); ty_obj(vec[method]);
ty_var(int); // ephemeral type var ty_var(int); // ephemeral type var
ty_local(ast.def_id); // type of a local var ty_local(ast.def_id); // type of a local var
ty_param(ast.def_id); // fn/tag type param ty_param(uint); // fn/tag type param
ty_type; ty_type;
ty_native; ty_native;
// TODO: ty_fn_arg(@t), for a possibly-aliased function argument // TODO: ty_fn_arg(@t), for a possibly-aliased function argument
@ -68,10 +68,8 @@ tag sty {
type unify_handler = obj { type unify_handler = obj {
fn resolve_local(ast.def_id id) -> @t; fn resolve_local(ast.def_id id) -> @t;
fn record_local(ast.def_id id, @t ty); fn record_local(ast.def_id id, @t ty);
fn unify_expected_param(ast.def_id id, @t expected, @t actual) fn unify_expected_param(uint id, @t expected, @t actual) -> unify_result;
-> unify_result; fn unify_actual_param(uint id, @t expected, @t actual) -> unify_result;
fn unify_actual_param(ast.def_id id, @t expected, @t actual)
-> unify_result;
}; };
tag type_err { tag type_err {
@ -94,8 +92,8 @@ tag unify_result {
} }
type ty_params_opt_and_ty = tup(option.t[vec[ast.def_id]], @ty.t); type ty_param_count_and_ty = tup(uint, @t);
type type_cache = hashmap[ast.def_id,ty_params_opt_and_ty]; type type_cache = hashmap[ast.def_id,ty_param_count_and_ty];
// Stringification // Stringification
@ -248,8 +246,7 @@ fn ty_to_str(&@t typ) -> str {
} }
case (ty_param(?id)) { case (ty_param(?id)) {
s += "<P" + util.common.istr(id._0) + ":" + s += "'" + _str.unsafe_from_bytes(vec(('a' as u8) + (id as u8)));
util.common.istr(id._1) + ">";
} }
} }
@ -558,12 +555,12 @@ fn type_is_signed(@t ty) -> bool {
fail; fail;
} }
fn type_param(@t ty) -> option.t[ast.def_id] { fn type_param(@t ty) -> option.t[uint] {
alt (ty.struct) { alt (ty.struct) {
case (ty_param(?id)) { ret some[ast.def_id](id); } case (ty_param(?id)) { ret some[uint](id); }
case (_) { /* fall through */ } case (_) { /* fall through */ }
} }
ret none[ast.def_id]; ret none[uint];
} }
fn plain_ty(&sty st) -> @t { fn plain_ty(&sty st) -> @t {
@ -605,18 +602,21 @@ fn ann_to_type(&ast.ann ann) -> @t {
} }
} }
// Returns the number of distinct type parameters in the given type.
fn count_ty_params(@t ty) -> uint { fn count_ty_params(@t ty) -> uint {
state obj ty_param_counter(@mutable vec[ast.def_id] param_ids) { state obj ty_param_counter(@mutable vec[uint] param_indices) {
fn fold_simple_ty(@t ty) -> @t { fn fold_simple_ty(@t ty) -> @t {
alt (ty.struct) { alt (ty.struct) {
case (ty_param(?param_id)) { case (ty_param(?param_idx)) {
for (ast.def_id other_param_id in *param_ids) { auto seen = false;
if (param_id._0 == other_param_id._0 && for (uint other_param_idx in *param_indices) {
param_id._1 == other_param_id._1) { if (param_idx == other_param_idx) {
ret ty; seen = true;
} }
} }
*param_ids += vec(param_id); if (!seen) {
*param_indices += vec(param_idx);
}
} }
case (_) { /* fall through */ } case (_) { /* fall through */ }
} }
@ -624,10 +624,10 @@ fn count_ty_params(@t ty) -> uint {
} }
} }
let vec[ast.def_id] param_ids_inner = vec(); let vec[uint] v = vec(); // FIXME: typechecker botch
let @mutable vec[ast.def_id] param_ids = @mutable param_ids_inner; let @mutable vec[uint] param_indices = @mutable v;
fold_ty(ty_param_counter(param_ids), ty); fold_ty(ty_param_counter(param_indices), ty);
ret _vec.len[ast.def_id](*param_ids); ret _vec.len[uint](*param_indices);
} }
// Type accessors for substructures of types // Type accessors for substructures of types
@ -674,59 +674,50 @@ fn is_fn_ty(@t fty) -> bool {
// Type accessors for AST nodes // Type accessors for AST nodes
// Given an item, returns the associated type as well as a list of the IDs of // Given an item, returns the associated type as well as the number of type
// its type parameters. // parameters it has.
type ty_params_and_ty = tup(vec[ast.def_id], @t); fn native_item_ty(@ast.native_item it) -> ty_param_count_and_ty {
fn native_item_ty(@ast.native_item it) -> ty_params_and_ty { auto ty_param_count;
auto ty_params;
auto result_ty; auto result_ty;
alt (it.node) { alt (it.node) {
case (ast.native_item_fn(_, _, _, ?tps, _, ?ann)) { case (ast.native_item_fn(_, _, _, ?tps, _, ?ann)) {
ty_params = tps; ty_param_count = _vec.len[ast.ty_param](tps);
result_ty = ann_to_type(ann); result_ty = ann_to_type(ann);
} }
} }
let vec[ast.def_id] ty_param_ids = vec(); ret tup(ty_param_count, result_ty);
for (ast.ty_param tp in ty_params) {
ty_param_ids += vec(tp.id);
}
ret tup(ty_param_ids, result_ty);
} }
fn item_ty(@ast.item it) -> ty_params_and_ty { fn item_ty(@ast.item it) -> ty_param_count_and_ty {
let vec[ast.ty_param] ty_params; auto ty_param_count;
auto result_ty; auto result_ty;
alt (it.node) { alt (it.node) {
case (ast.item_const(_, _, _, _, ?ann)) { case (ast.item_const(_, _, _, _, ?ann)) {
ty_params = vec(); ty_param_count = 0u;
result_ty = ann_to_type(ann); result_ty = ann_to_type(ann);
} }
case (ast.item_fn(_, _, ?tps, _, ?ann)) { case (ast.item_fn(_, _, ?tps, _, ?ann)) {
ty_params = tps; ty_param_count = _vec.len[ast.ty_param](tps);
result_ty = ann_to_type(ann); result_ty = ann_to_type(ann);
} }
case (ast.item_mod(_, _, _)) { case (ast.item_mod(_, _, _)) {
fail; // modules are typeless fail; // modules are typeless
} }
case (ast.item_ty(_, _, ?tps, _, ?ann)) { case (ast.item_ty(_, _, ?tps, _, ?ann)) {
ty_params = tps; ty_param_count = _vec.len[ast.ty_param](tps);
result_ty = ann_to_type(ann); result_ty = ann_to_type(ann);
} }
case (ast.item_tag(_, _, ?tps, ?did, ?ann)) { case (ast.item_tag(_, _, ?tps, ?did, ?ann)) {
ty_params = tps; ty_param_count = _vec.len[ast.ty_param](tps);
result_ty = ann_to_type(ann); result_ty = ann_to_type(ann);
} }
case (ast.item_obj(_, _, ?tps, _, ?ann)) { case (ast.item_obj(_, _, ?tps, _, ?ann)) {
ty_params = tps; ty_param_count = _vec.len[ast.ty_param](tps);
result_ty = ann_to_type(ann); result_ty = ann_to_type(ann);
} }
} }
let vec[ast.def_id] ty_param_ids = vec(); ret tup(ty_param_count, result_ty);
for (ast.ty_param tp in ty_params) {
ty_param_ids += vec(tp.id);
}
ret tup(ty_param_ids, result_ty);
} }
fn stmt_ty(@ast.stmt s) -> @t { fn stmt_ty(@ast.stmt s) -> @t {
@ -1608,24 +1599,25 @@ fn type_err_to_str(&ty.type_err err) -> str {
// Type parameter resolution, used in translation and typechecking // Type parameter resolution, used in translation and typechecking
fn resolve_ty_params(ty_params_and_ty ty_params_and_polyty, fn resolve_ty_params(ty_param_count_and_ty ty_params_and_polyty,
@t monoty) -> vec[@t] { @t monoty) -> vec[@t] {
obj resolve_ty_params_handler(@hashmap[ast.def_id,@t] bindings) { // TODO: Use a vector, not a hashmap here.
obj resolve_ty_params_handler(@hashmap[uint,@t] bindings) {
fn resolve_local(ast.def_id id) -> @t { log "resolve local"; fail; } fn resolve_local(ast.def_id id) -> @t { log "resolve local"; fail; }
fn record_local(ast.def_id id, @t ty) { log "record local"; fail; } fn record_local(ast.def_id id, @t ty) { log "record local"; fail; }
fn unify_expected_param(ast.def_id id, @t expected, @t actual) fn unify_expected_param(uint id, @t expected, @t actual)
-> unify_result { -> unify_result {
bindings.insert(id, actual); bindings.insert(id, actual);
ret ures_ok(actual); ret ures_ok(actual);
} }
fn unify_actual_param(ast.def_id id, @t expected, @t actual) fn unify_actual_param(uint id, @t expected, @t actual)
-> unify_result { -> unify_result {
bindings.insert(id, expected); bindings.insert(id, expected);
ret ures_ok(expected); ret ures_ok(expected);
} }
} }
auto bindings = @new_def_hash[@t](); auto bindings = @common.new_uint_hash[@t]();
auto handler = resolve_ty_params_handler(bindings); auto handler = resolve_ty_params_handler(bindings);
auto unify_res = unify(ty_params_and_polyty._1, monoty, handler); auto unify_res = unify(ty_params_and_polyty._1, monoty, handler);
@ -1639,10 +1631,12 @@ fn resolve_ty_params(ty_params_and_ty ty_params_and_polyty,
} }
let vec[@t] result_tys = vec(); let vec[@t] result_tys = vec();
auto ty_param_ids = ty_params_and_polyty._0; auto ty_param_count = ty_params_and_polyty._0;
for (ast.def_id tp in ty_param_ids) { auto i = 0u;
check (bindings.contains_key(tp)); while (i < ty_param_count) {
result_tys += vec(bindings.get(tp)); check (bindings.contains_key(i));
result_tys += vec(bindings.get(i));
i += 1u;
} }
ret result_tys; ret result_tys;
@ -1650,45 +1644,19 @@ fn resolve_ty_params(ty_params_and_ty ty_params_and_polyty,
// Performs type parameter replacement using the supplied mapping from // Performs type parameter replacement using the supplied mapping from
// parameter IDs to types. // parameter IDs to types.
fn replace_type_params(@t typ, hashmap[ast.def_id,@t] param_map) -> @t { fn substitute_type_params(vec[@t] bindings, @t typ) -> @t {
state obj param_replacer(hashmap[ast.def_id,@t] param_map) { state obj param_replacer(vec[@t] bindings) {
fn fold_simple_ty(@t typ) -> @t { fn fold_simple_ty(@t typ) -> @t {
alt (typ.struct) { alt (typ.struct) {
case (ty_param(?param_def)) { case (ty_param(?param_index)) { ret bindings.(param_index); }
if (param_map.contains_key(param_def)) { case (_) { ret typ; }
ret param_map.get(param_def);
} else {
ret typ;
}
}
case (_) {
ret typ;
} }
} }
} }
} auto replacer = param_replacer(bindings);
auto replacer = param_replacer(param_map);
ret fold_ty(replacer, typ); ret fold_ty(replacer, typ);
} }
// Substitutes the type parameters specified by @ty_params with the
// corresponding types in @bound in the given type. The two vectors must have
// the same length.
fn substitute_ty_params(vec[ast.def_id] ty_params, vec[@t] bound, @t ty)
-> @t {
auto ty_param_len = _vec.len[ast.def_id](ty_params);
check (ty_param_len == _vec.len[@t](bound));
auto bindings = common.new_def_hash[@t]();
auto i = 0u;
while (i < ty_param_len) {
bindings.insert(ty_params.(i), bound.(i));
i += 1u;
}
ret replace_type_params(ty, bindings);
}
fn def_has_ty_params(&ast.def def) -> bool { fn def_has_ty_params(&ast.def def) -> bool {
alt (def) { alt (def) {
@ -1712,7 +1680,7 @@ fn def_has_ty_params(&ast.def def) -> bool {
// If the given item is in an external crate, looks up its type and adds it to // 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. // the type cache. Returns the type parameters and type.
fn lookup_item_type(session.session sess, &type_cache cache, fn lookup_item_type(session.session sess, &type_cache cache,
ast.def_id did) -> ty_params_opt_and_ty { ast.def_id did) -> ty_param_count_and_ty {
if (did._0 == sess.get_targ_crate_num()) { if (did._0 == sess.get_targ_crate_num()) {
// The item is in this crate. The caller should have added it to the // The item is in this crate. The caller should have added it to the
// type cache already; we simply return it. // type cache already; we simply return it.
@ -1729,14 +1697,6 @@ fn lookup_item_type(session.session sess, &type_cache cache,
ret tyt; ret tyt;
} }
// A convenience function to retrive type parameters and a type when it's
// known that the item supports generics (functions, variants, objects).
fn lookup_generic_item_type(session.session sess, &type_cache cache,
ast.def_id did) -> ty_params_and_ty {
auto tp_opt_and_ty = lookup_item_type(sess, cache, did);
ret tup(option.get[vec[ast.def_id]](tp_opt_and_ty._0), tp_opt_and_ty._1);
}
// Local Variables: // Local Variables:
// mode: rust // mode: rust

View file

@ -22,7 +22,7 @@ import middle.ty.plain_ty;
import middle.ty.ty_to_str; import middle.ty.ty_to_str;
import middle.ty.type_is_integral; import middle.ty.type_is_integral;
import middle.ty.type_is_scalar; import middle.ty.type_is_scalar;
import middle.ty.ty_params_opt_and_ty; import middle.ty.ty_param_count_and_ty;
import middle.ty.ty_nil; import middle.ty.ty_nil;
import std._str; import std._str;
@ -59,7 +59,7 @@ type fn_ctxt = rec(@ty.t ret_ty,
@crate_ctxt ccx); @crate_ctxt ccx);
// Used for ast_ty_to_ty() below. // Used for ast_ty_to_ty() below.
type ty_getter = fn(ast.def_id) -> ty.ty_params_opt_and_ty; type ty_getter = fn(ast.def_id) -> ty.ty_param_count_and_ty;
// Turns a type into an ann_type, using defaults for other fields. // Turns a type into an ann_type, using defaults for other fields.
fn triv_ann(@ty.t t) -> ann { fn triv_ann(@ty.t t) -> ann {
@ -75,8 +75,7 @@ fn boring_ann() -> ann {
// Replaces parameter types inside a type with type variables. // Replaces parameter types inside a type with type variables.
fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t {
state obj ty_generalizer(@crate_ctxt cx, state obj ty_generalizer(@crate_ctxt cx,
@hashmap[ast.def_id,@ty.t] @hashmap[uint,@ty.t] ty_params_to_ty_vars) {
ty_params_to_ty_vars) {
fn fold_simple_ty(@ty.t t) -> @ty.t { fn fold_simple_ty(@ty.t t) -> @ty.t {
alt (t.struct) { alt (t.struct) {
case (ty.ty_param(?pid)) { case (ty.ty_param(?pid)) {
@ -93,7 +92,7 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t {
} }
} }
auto generalizer = ty_generalizer(cx, @common.new_def_hash[@ty.t]()); auto generalizer = ty_generalizer(cx, @common.new_uint_hash[@ty.t]());
ret ty.fold_ty(generalizer, t); ret ty.fold_ty(generalizer, t);
} }
@ -101,57 +100,39 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t {
// expression. // expression.
fn substitute_ty_params(&@crate_ctxt ccx, fn substitute_ty_params(&@crate_ctxt ccx,
@ty.t typ, @ty.t typ,
vec[ast.def_id] ty_params, uint ty_param_count,
vec[@ty.t] supplied, vec[@ty.t] supplied,
&span sp) -> @ty.t { &span sp) -> @ty.t {
state obj ty_substituter(@crate_ctxt ccx, state obj ty_substituter(@crate_ctxt ccx, vec[@ty.t] supplied) {
vec[ast.def_id] ty_params,
vec[@ty.t] supplied) {
fn fold_simple_ty(@ty.t typ) -> @ty.t { fn fold_simple_ty(@ty.t typ) -> @ty.t {
alt (typ.struct) { alt (typ.struct) {
case (ty.ty_param(?pid)) { case (ty.ty_param(?pid)) { ret supplied.(pid); }
// Find the index of the type parameter.
auto ty_param_len = _vec.len[ast.def_id](ty_params);
auto i = 0u;
while (i < ty_param_len &&
!common.def_eq(pid, ty_params.(i))) {
i += 1u;
}
if (i == ty_param_len) {
log "substitute_ty_params(): " +
"no ty param for param id!";
fail;
}
// Substitute it in.
ret supplied.(i);
}
case (_) { ret typ; } case (_) { ret typ; }
} }
} }
} }
auto ty_param_len = _vec.len[ast.def_id](ty_params);
auto supplied_len = _vec.len[@ty.t](supplied); auto supplied_len = _vec.len[@ty.t](supplied);
if (ty_param_len != supplied_len) { if (ty_param_count != supplied_len) {
ccx.sess.span_err(sp, "expected " + _uint.to_str(ty_param_len, 10u) + ccx.sess.span_err(sp, "expected " +
_uint.to_str(ty_param_count, 10u) +
" type parameter(s) but found " + " type parameter(s) but found " +
_uint.to_str(supplied_len, 10u) + " parameter(s)"); _uint.to_str(supplied_len, 10u) + " parameter(s)");
fail; fail;
} }
auto substituter = ty_substituter(ccx, ty_params, supplied); auto substituter = ty_substituter(ccx, supplied);
ret ty.fold_ty(substituter, typ); ret ty.fold_ty(substituter, typ);
} }
// Returns the type parameters and the type for the given definition. // Returns the type parameter count and the type for the given definition.
fn ty_params_and_ty_for_def(@fn_ctxt fcx, &ast.def defn) fn ty_param_count_and_ty_for_def(@fn_ctxt fcx, &ast.def defn)
-> ty_params_opt_and_ty { -> ty_param_count_and_ty {
alt (defn) { alt (defn) {
case (ast.def_arg(?id)) { case (ast.def_arg(?id)) {
check (fcx.locals.contains_key(id)); check (fcx.locals.contains_key(id));
ret tup(none[vec[ast.def_id]], fcx.locals.get(id)); ret tup(0u, fcx.locals.get(id));
} }
case (ast.def_local(?id)) { case (ast.def_local(?id)) {
auto t; auto t;
@ -159,11 +140,11 @@ fn ty_params_and_ty_for_def(@fn_ctxt fcx, &ast.def defn)
case (some[@ty.t](?t1)) { t = t1; } case (some[@ty.t](?t1)) { t = t1; }
case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); } case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); }
} }
ret tup(none[vec[ast.def_id]], t); ret tup(0u, t);
} }
case (ast.def_obj_field(?id)) { case (ast.def_obj_field(?id)) {
check (fcx.locals.contains_key(id)); check (fcx.locals.contains_key(id));
ret tup(none[vec[ast.def_id]], fcx.locals.get(id)); ret tup(0u, fcx.locals.get(id));
} }
case (ast.def_fn(?id)) { case (ast.def_fn(?id)) {
ret ty.lookup_item_type(fcx.ccx.sess, fcx.ccx.type_cache, id); ret ty.lookup_item_type(fcx.ccx.sess, fcx.ccx.type_cache, id);
@ -179,7 +160,7 @@ fn ty_params_and_ty_for_def(@fn_ctxt fcx, &ast.def defn)
} }
case (ast.def_binding(?id)) { case (ast.def_binding(?id)) {
check (fcx.locals.contains_key(id)); check (fcx.locals.contains_key(id));
ret tup(none[vec[ast.def_id]], fcx.locals.get(id)); ret tup(0u, fcx.locals.get(id));
} }
case (ast.def_obj(?id)) { case (ast.def_obj(?id)) {
ret ty.lookup_item_type(fcx.ccx.sess, fcx.ccx.type_cache, id); ret ty.lookup_item_type(fcx.ccx.sess, fcx.ccx.type_cache, id);
@ -188,7 +169,7 @@ fn ty_params_and_ty_for_def(@fn_ctxt fcx, &ast.def defn)
case (ast.def_mod(_)) { case (ast.def_mod(_)) {
// Hopefully part of a path. // Hopefully part of a path.
// TODO: return a type that's more poisonous, perhaps? // TODO: return a type that's more poisonous, perhaps?
ret tup(none[vec[ast.def_id]], plain_ty(ty.ty_nil)); ret tup(0u, plain_ty(ty.ty_nil));
} }
case (ast.def_ty(_)) { case (ast.def_ty(_)) {
@ -205,10 +186,10 @@ fn ty_params_and_ty_for_def(@fn_ctxt fcx, &ast.def defn)
} }
// Instantiates the given path, which must refer to an item with the given // Instantiates the given path, which must refer to an item with the given
// type parameters and type. // number of type parameters and type.
fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_params_opt_and_ty tpt, fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_param_count_and_ty tpt,
&span sp) -> ast.ann { &span sp) -> ast.ann {
auto ty_params = tpt._0; auto ty_param_count = tpt._0;
auto t = tpt._1; auto t = tpt._1;
auto ty_substs_opt; auto ty_substs_opt;
@ -222,61 +203,25 @@ fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_params_opt_and_ty tpt,
} }
ty_substs_opt = some[vec[@ty.t]](ty_substs); ty_substs_opt = some[vec[@ty.t]](ty_substs);
alt (ty_params) { if (ty_param_count == 0u) {
case (none[vec[ast.def_id]]) { fcx.ccx.sess.span_err(sp, "this item does not take type " +
fcx.ccx.sess.span_err(sp, "this kind of item may not take " + "parameters");
"type parameters");
fail; fail;
} }
case (some[vec[ast.def_id]](?tps)) {
t = substitute_ty_params(fcx.ccx, t, tps, ty_substs, sp); t = substitute_ty_params(fcx.ccx, t, ty_param_count, ty_substs, sp);
}
}
} else { } else {
ty_substs_opt = none[vec[@ty.t]]; ty_substs_opt = none[vec[@ty.t]];
alt (ty_params) { if (ty_param_count > 0u) {
case (none[vec[ast.def_id]]) { /* nothing */ } // We will acquire the type parameters through unification.
case (some[vec[ast.def_id]](_)) {
// We will acquire the type parameters through
// unification.
t = generalize_ty(fcx.ccx, t); t = generalize_ty(fcx.ccx, t);
} }
} }
}
ret ast.ann_type(t, ty_substs_opt, none[@ts_ann]); ret ast.ann_type(t, ty_substs_opt, none[@ts_ann]);
} }
// Returns the type parameters and polytype of an item, if it's an item that
// supports type parameters.
//
// TODO: This function is a little silly in the presence of the new
// lookup_item_type(); remove this in favor of lookup_item_type() if possible.
fn ty_params_for_item(@crate_ctxt ccx, &ast.def d)
-> option.t[ty.ty_params_and_ty] {
auto did;
alt (d) {
case (ast.def_fn(?id)) { did = id; }
case (ast.def_obj(?id)) { did = id; }
case (ast.def_obj_field(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_mod(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_const(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_arg(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_local(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_variant(_, ?vid)) { did = vid; }
case (ast.def_ty(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_ty_arg(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_binding(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_use(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_native_ty(_)) { ret none[ty.ty_params_and_ty]; }
case (ast.def_native_fn(?id)) { did = id; }
}
auto tpt = ty.lookup_generic_item_type(ccx.sess, ccx.type_cache, did);
ret some[ty.ty_params_and_ty](tpt);
}
// Parses the programmer's textual representation of a type into our internal // Parses the programmer's textual representation of a type into our internal
// notion of a type. `getter` is a function that returns the type // notion of a type. `getter` is a function that returns the type
// corresponding to a definition ID. // corresponding to a definition ID.
@ -295,25 +240,20 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t {
// TODO: maybe record cname chains so we can do // TODO: maybe record cname chains so we can do
// "foo = int" like OCaml? // "foo = int" like OCaml?
auto params_opt_and_ty = getter(id); auto params_opt_and_ty = getter(id);
alt (params_opt_and_ty._0) {
case (none[vec[ast.def_id]]) {
// FIXME: Session error. This is completely user-unfriendly.
log "item has no type parameters";
fail;
}
case (some[vec[ast.def_id]](?params)) {
auto num_type_args = _vec.len[@ast.ty](args);
check(num_type_args == _vec.len[ast.def_id](params));
auto param_map = common.new_def_hash[@ty.t](); if (params_opt_and_ty._0 == 0u) {
for each (uint i in _uint.range(0u, num_type_args)) { ret params_opt_and_ty._1;
auto arg = args.(i);
auto param = params.(i);
param_map.insert(param, ast_ty_to_ty(getter, arg));
}
ret ty.replace_type_params(params_opt_and_ty._1, param_map);
} }
// The typedef is type-parametric. Do the type substitution.
//
// TODO: Make sure the number of supplied bindings matches the number
// of type parameters in the typedef. Emit a friendly error otherwise.
let vec[@ty.t] param_bindings = vec();
for (@ast.ty ast_ty in args) {
param_bindings += vec(ast_ty_to_ty(getter, ast_ty));
} }
ret ty.substitute_type_params(param_bindings, params_opt_and_ty._1);
} }
auto mut = ast.imm; auto mut = ast.imm;
@ -403,7 +343,7 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t {
// A convenience function to use a crate_ctxt to resolve names for // A convenience function to use a crate_ctxt to resolve names for
// ast_ty_to_ty. // ast_ty_to_ty.
fn ast_ty_to_ty_crate(@crate_ctxt ccx, &@ast.ty ast_ty) -> @ty.t { fn ast_ty_to_ty_crate(@crate_ctxt ccx, &@ast.ty ast_ty) -> @ty.t {
fn getter(@crate_ctxt ccx, ast.def_id id) -> ty.ty_params_opt_and_ty { fn getter(@crate_ctxt ccx, ast.def_id id) -> ty.ty_param_count_and_ty {
ret ty.lookup_item_type(ccx.sess, ccx.type_cache, id); ret ty.lookup_item_type(ccx.sess, ccx.type_cache, id);
} }
auto f = bind getter(ccx, _); auto f = bind getter(ccx, _);
@ -422,14 +362,6 @@ fn ast_ty_to_ty_crate(@crate_ctxt ccx, &@ast.ty ast_ty) -> @ty.t {
// We then annotate the AST with the resulting types and return the annotated // We then annotate the AST with the resulting types and return the annotated
// AST, along with a table mapping item IDs to their types. // AST, along with a table mapping item IDs to their types.
fn ty_params_to_def_ids(vec[ast.ty_param] tps) -> vec[ast.def_id] {
let vec[ast.def_id] result = vec();
for (ast.ty_param tp in tps) {
result += vec(tp.id);
}
ret result;
}
fn ty_of_fn_decl(@ty_item_table id_to_ty_item, fn ty_of_fn_decl(@ty_item_table id_to_ty_item,
ty.type_cache type_cache, ty.type_cache type_cache,
fn(&@ast.ty ast_ty) -> @ty.t convert, fn(&@ast.ty ast_ty) -> @ty.t convert,
@ -437,12 +369,12 @@ fn ty_of_fn_decl(@ty_item_table id_to_ty_item,
&ast.fn_decl decl, &ast.fn_decl decl,
ast.proto proto, ast.proto proto,
vec[ast.ty_param] ty_params, vec[ast.ty_param] ty_params,
ast.def_id def_id) -> ty.ty_params_opt_and_ty { ast.def_id def_id) -> ty.ty_param_count_and_ty {
auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs); auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs);
auto output_ty = convert(decl.output); auto output_ty = convert(decl.output);
auto t_fn = plain_ty(ty.ty_fn(proto, input_tys, output_ty)); auto t_fn = plain_ty(ty.ty_fn(proto, input_tys, output_ty));
auto params_opt = some[vec[ast.def_id]](ty_params_to_def_ids(ty_params)); auto ty_param_count = _vec.len[ast.ty_param](ty_params);
auto tpt = tup(params_opt, t_fn); auto tpt = tup(ty_param_count, t_fn);
type_cache.insert(def_id, tpt); type_cache.insert(def_id, tpt);
ret tpt; ret tpt;
} }
@ -454,12 +386,12 @@ fn ty_of_native_fn_decl(@ty_item_table id_to_ty_item,
&ast.fn_decl decl, &ast.fn_decl decl,
ast.native_abi abi, ast.native_abi abi,
vec[ast.ty_param] ty_params, vec[ast.ty_param] ty_params,
ast.def_id def_id) -> ty.ty_params_opt_and_ty { ast.def_id def_id) -> ty.ty_param_count_and_ty {
auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs); auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs);
auto output_ty = convert(decl.output); auto output_ty = convert(decl.output);
auto t_fn = plain_ty(ty.ty_native_fn(abi, input_tys, output_ty)); auto t_fn = plain_ty(ty.ty_native_fn(abi, input_tys, output_ty));
auto params_opt = some[vec[ast.def_id]](ty_params_to_def_ids(ty_params)); auto ty_param_count = _vec.len[ast.ty_param](ty_params);
auto tpt = tup(params_opt, t_fn); auto tpt = tup(ty_param_count, t_fn);
type_cache.insert(def_id, tpt); type_cache.insert(def_id, tpt);
ret tpt; ret tpt;
} }
@ -470,7 +402,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
fn getter(session.session sess, fn getter(session.session sess,
@ty_item_table id_to_ty_item, @ty_item_table id_to_ty_item,
ty.type_cache type_cache, ty.type_cache type_cache,
ast.def_id id) -> ty.ty_params_opt_and_ty { ast.def_id id) -> ty.ty_param_count_and_ty {
if (id._0 != sess.get_targ_crate_num()) { if (id._0 != sess.get_targ_crate_num()) {
// This is a type we need to load in from the crate reader. // This is a type we need to load in from the crate reader.
@ -520,16 +452,15 @@ fn collect_item_types(session.session sess, @ast.crate crate)
ty.type_cache type_cache, ty.type_cache type_cache,
&ast.ident id, &ast.ident id,
&ast._obj obj_info, &ast._obj obj_info,
vec[ast.ty_param] ty_params) -> ty.ty_params_opt_and_ty { vec[ast.ty_param] ty_params) -> ty.ty_param_count_and_ty {
auto f = bind ty_of_method(sess, id_to_ty_item, type_cache, _); auto f = bind ty_of_method(sess, id_to_ty_item, type_cache, _);
auto methods = auto methods =
_vec.map[@ast.method,method](f, obj_info.methods); _vec.map[@ast.method,method](f, obj_info.methods);
auto t_obj = @rec(struct=ty.ty_obj(ty.sort_methods(methods)), auto t_obj = @rec(struct=ty.ty_obj(ty.sort_methods(methods)),
cname=some[str](id)); cname=some[str](id));
auto params = ty_params_to_def_ids(ty_params); auto ty_param_count = _vec.len[ast.ty_param](ty_params);
auto params_opt = some[vec[ast.def_id]](params); ret tup(ty_param_count, t_obj);
ret tup(params_opt, t_obj);
} }
fn ty_of_obj_ctor(session.session sess, fn ty_of_obj_ctor(session.session sess,
@ -539,7 +470,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
&ast._obj obj_info, &ast._obj obj_info,
ast.def_id obj_ty_id, ast.def_id obj_ty_id,
vec[ast.ty_param] ty_params) vec[ast.ty_param] ty_params)
-> ty.ty_params_opt_and_ty { -> ty.ty_param_count_and_ty {
auto t_obj = ty_of_obj(sess, id_to_ty_item, type_cache, auto t_obj = ty_of_obj(sess, id_to_ty_item, type_cache,
id, obj_info, ty_params); id, obj_info, ty_params);
let vec[arg] t_inputs = vec(); let vec[arg] t_inputs = vec();
@ -558,7 +489,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
fn ty_of_item(session.session sess, fn ty_of_item(session.session sess,
@ty_item_table id_to_ty_item, @ty_item_table id_to_ty_item,
ty.type_cache type_cache, ty.type_cache type_cache,
@ast.item it) -> ty.ty_params_opt_and_ty { @ast.item it) -> ty.ty_param_count_and_ty {
auto get = bind getter(sess, id_to_ty_item, type_cache, _); auto get = bind getter(sess, id_to_ty_item, type_cache, _);
auto convert = bind ast_ty_to_ty(get, _); auto convert = bind ast_ty_to_ty(get, _);
@ -567,7 +498,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
case (ast.item_const(?ident, ?t, _, ?def_id, _)) { case (ast.item_const(?ident, ?t, _, ?def_id, _)) {
auto typ = convert(t); auto typ = convert(t);
type_cache.insert(def_id, tup(none[vec[ast.def_id]], typ)); type_cache.insert(def_id, tup(0u, typ));
} }
case (ast.item_fn(?ident, ?fn_info, ?tps, ?def_id, _)) { case (ast.item_fn(?ident, ?fn_info, ?tps, ?def_id, _)) {
@ -597,9 +528,8 @@ fn collect_item_types(session.session sess, @ast.crate crate)
// Tell ast_ty_to_ty() that we want to perform a recursive // Tell ast_ty_to_ty() that we want to perform a recursive
// call to resolve any named types. // call to resolve any named types.
auto typ = convert(ty); auto typ = convert(ty);
auto params = ty_params_to_def_ids(tps); auto ty_param_count = _vec.len[ast.ty_param](tps);
auto params_opt = some[vec[ast.def_id]](params); auto tpt = tup(ty_param_count, typ);
auto tpt = tup(params_opt, typ);
type_cache.insert(def_id, tpt); type_cache.insert(def_id, tpt);
ret tpt; ret tpt;
} }
@ -607,14 +537,17 @@ fn collect_item_types(session.session sess, @ast.crate crate)
case (ast.item_tag(_, _, ?tps, ?def_id, _)) { case (ast.item_tag(_, _, ?tps, ?def_id, _)) {
// Create a new generic polytype. // Create a new generic polytype.
let vec[@ty.t] subtys = vec(); let vec[@ty.t] subtys = vec();
auto i = 0u;
for (ast.ty_param tp in tps) { for (ast.ty_param tp in tps) {
subtys += vec(plain_ty(ty.ty_param(tp.id))); subtys += vec(plain_ty(ty.ty_param(i)));
i += 1u;
} }
auto t = plain_ty(ty.ty_tag(def_id, subtys)); auto t = plain_ty(ty.ty_tag(def_id, subtys));
auto params = ty_params_to_def_ids(tps); auto ty_param_count = _vec.len[ast.ty_param](tps);
auto params_opt = some[vec[ast.def_id]](params); auto tpt = tup(ty_param_count, t);
auto tpt = tup(params_opt, t);
type_cache.insert(def_id, tpt); type_cache.insert(def_id, tpt);
ret tpt; ret tpt;
} }
@ -628,7 +561,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
@ty_item_table id_to_ty_item, @ty_item_table id_to_ty_item,
ty.type_cache type_cache, ty.type_cache type_cache,
@ast.native_item it, @ast.native_item it,
ast.native_abi abi) -> ty.ty_params_opt_and_ty { ast.native_abi abi) -> ty.ty_param_count_and_ty {
alt (it.node) { alt (it.node) {
case (ast.native_item_fn(?ident, ?lname, ?fn_decl, case (ast.native_item_fn(?ident, ?lname, ?fn_decl,
?params, ?def_id, _)) { ?params, ?def_id, _)) {
@ -645,7 +578,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
} }
auto t = @rec(struct=ty.ty_native, cname=none[str]); auto t = @rec(struct=ty.ty_native, cname=none[str]);
auto tpt = tup(none[vec[ast.def_id]], t); auto tpt = tup(0u, t);
type_cache.insert(def_id, tpt); type_cache.insert(def_id, tpt);
ret tpt; ret tpt;
} }
@ -663,12 +596,13 @@ fn collect_item_types(session.session sess, @ast.crate crate)
// Create a set of parameter types shared among all the variants. // Create a set of parameter types shared among all the variants.
let vec[@ty.t] ty_param_tys = vec(); let vec[@ty.t] ty_param_tys = vec();
auto i = 0u;
for (ast.ty_param tp in ty_params) { for (ast.ty_param tp in ty_params) {
ty_param_tys += vec(plain_ty(ty.ty_param(tp.id))); ty_param_tys += vec(plain_ty(ty.ty_param(i)));
i += 1u;
} }
auto params = ty_params_to_def_ids(ty_params); auto ty_param_count = _vec.len[ast.ty_param](ty_params);
auto params_opt = some[vec[ast.def_id]](params);
for (ast.variant variant in variants) { for (ast.variant variant in variants) {
// Nullary tag constructors get turned into constants; n-ary tag // Nullary tag constructors get turned into constants; n-ary tag
@ -690,7 +624,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
result_ty = plain_ty(ty.ty_fn(ast.proto_fn, args, tag_t)); result_ty = plain_ty(ty.ty_fn(ast.proto_fn, args, tag_t));
} }
auto tpt = tup(params_opt, result_ty); auto tpt = tup(ty_param_count, result_ty);
type_cache.insert(variant.node.id, tpt); type_cache.insert(variant.node.id, tpt);
auto variant_t = rec(ann=triv_ann(result_ty) auto variant_t = rec(ann=triv_ann(result_ty)
with variant.node with variant.node
@ -743,7 +677,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
// Second pass: translate the types of all items. // Second pass: translate the types of all items.
auto type_cache = common.new_def_hash[ty.ty_params_opt_and_ty](); auto type_cache = common.new_def_hash[ty.ty_param_count_and_ty]();
type env = rec(session.session sess, type env = rec(session.session sess,
@ty_item_table id_to_ty_item, @ty_item_table id_to_ty_item,
@ -920,25 +854,21 @@ fn unify(&@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> ty.unify_result {
fn record_local(ast.def_id id, @ty.t t) { fn record_local(ast.def_id id, @ty.t t) {
fcx.locals.insert(id, t); fcx.locals.insert(id, t);
} }
fn unify_expected_param(ast.def_id id, @ty.t expected, @ty.t actual) fn unify_expected_param(uint id, @ty.t expected, @ty.t actual)
-> ty.unify_result { -> ty.unify_result {
alt (actual.struct) { alt (actual.struct) {
case (ty.ty_param(?actual_id)) { case (ty.ty_param(?actual_id)) {
if (id._0 == actual_id._0 && id._1 == actual_id._1) { if (id == actual_id) { ret ty.ures_ok(expected); }
ret ty.ures_ok(expected);
}
} }
case (_) { /* fall through */ } case (_) { /* fall through */ }
} }
ret ty.ures_err(ty.terr_mismatch, expected, actual); ret ty.ures_err(ty.terr_mismatch, expected, actual);
} }
fn unify_actual_param(ast.def_id id, @ty.t expected, @ty.t actual) fn unify_actual_param(uint id, @ty.t expected, @ty.t actual)
-> ty.unify_result { -> ty.unify_result {
alt (expected.struct) { alt (expected.struct) {
case (ty.ty_param(?expected_id)) { case (ty.ty_param(?expected_id)) {
if (id._0 == expected_id._0 && id._1 == expected_id._1) { if (id == expected_id) { ret ty.ures_ok(actual); }
ret ty.ures_ok(actual);
}
} }
case (_) { /* fall through */ } case (_) { /* fall through */ }
} }
@ -1087,7 +1017,7 @@ mod Pushdown {
// Figure out the type parameters of the tag. // Figure out the type parameters of the tag.
auto tag_id = option.get[ast.variant_def](vdef_opt)._0; auto tag_id = option.get[ast.variant_def](vdef_opt)._0;
auto tpt = ty.lookup_generic_item_type(fcx.ccx.sess, auto tpt = ty.lookup_item_type(fcx.ccx.sess,
fcx.ccx.type_cache, tag_id); fcx.ccx.type_cache, tag_id);
auto ty_params = tpt._0; auto ty_params = tpt._0;
@ -1367,16 +1297,11 @@ mod Pushdown {
alt (tps_opt) { alt (tps_opt) {
case (none[vec[@ty.t]]) { case (none[vec[@ty.t]]) {
auto defn = option.get[ast.def](d); auto defn = option.get[ast.def](d);
alt (ty_params_for_item(fcx.ccx, defn)) { auto tpt =
case (none[ty.ty_params_and_ty]) { ty_param_count_and_ty_for_def(fcx, defn);
ty_params_opt = none[vec[@ty.t]];
}
case (some[ty.ty_params_and_ty](?tpt)) {
auto tps = ty.resolve_ty_params(tpt, t); auto tps = ty.resolve_ty_params(tpt, t);
ty_params_opt = some[vec[@ty.t]](tps); ty_params_opt = some[vec[@ty.t]](tps);
} }
}
}
case (some[vec[@ty.t]](?tps)) { case (some[vec[@ty.t]](?tps)) {
ty_params_opt = some[vec[@ty.t]](tps); ty_params_opt = some[vec[@ty.t]](tps);
} }
@ -1841,7 +1766,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto t = plain_ty(ty.ty_nil); auto t = plain_ty(ty.ty_nil);
check (defopt != none[ast.def]); check (defopt != none[ast.def]);
auto defn = option.get[ast.def](defopt); auto defn = option.get[ast.def](defopt);
auto tpt = ty_params_and_ty_for_def(fcx, defn); auto tpt = ty_param_count_and_ty_for_def(fcx, defn);
auto ann = instantiate_path(fcx, pth, tpt, expr.span); auto ann = instantiate_path(fcx, pth, tpt, expr.span);
ret @fold.respan[ast.expr_](expr.span, ret @fold.respan[ast.expr_](expr.span,
ast.expr_path(pth, defopt, ann)); ast.expr_path(pth, defopt, ann));
@ -2217,13 +2142,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto this_obj_id = fcx.ccx.this_obj; auto this_obj_id = fcx.ccx.this_obj;
alt (this_obj_id) { alt (this_obj_id) {
case (some[ast.def_id](?def_id)) { case (some[ast.def_id](?def_id)) {
auto this_obj_tpt = fcx.ccx.type_cache.find(def_id); this_obj_ty = ty.lookup_item_type(fcx.ccx.sess,
alt (this_obj_tpt) { fcx.ccx.type_cache, def_id)._1;
case (some[ty_params_opt_and_ty](?tpt)) {
this_obj_ty = tpt._1;
}
case (_) { fail; }
}
} }
case (_) { fail; } case (_) { fail; }
} }

View file

@ -796,7 +796,7 @@ impure fn print_type_params(ps s, vec[ast.ty_param] params) {
if (_vec.len[ast.ty_param](params) > 0u) { if (_vec.len[ast.ty_param](params) > 0u) {
wrd(s.s, "["); wrd(s.s, "[");
impure fn printParam(ps s, &ast.ty_param param) { impure fn printParam(ps s, &ast.ty_param param) {
wrd(s.s, param.ident); wrd(s.s, param);
} }
auto f = printParam; auto f = printParam;
commasep[ast.ty_param](s, params, f); commasep[ast.ty_param](s, params, f);