diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 50517f003c3..dfc69695c26 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -17,7 +17,7 @@ type crate_num = int; type def_num = int; 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. tag ann { @@ -39,7 +39,7 @@ tag def { def_upvar(def_id); def_variant(def_id /* tag */, def_id /* variant */); def_ty(def_id); - def_ty_arg(def_id); + def_ty_arg(uint); def_binding(def_id); def_use(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_variant(_, ?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_use(?id)) { ret id; } case (def_native_ty(?id)) { ret id; } diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index 7fc6e24726c..b70153803c8 100644 --- a/src/comp/front/creader.rs +++ b/src/comp/front/creader.rs @@ -131,7 +131,7 @@ impure fn parse_sty(@pstate st, str_def sd) -> ty.sty { st.pos = st.pos + 1u; 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 ('V') {ret ty.ty_vec(parse_mt(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, _)); } -fn item_ty_params(&ebml.doc item, int this_cnum) -> vec[ast.def_id] { - let vec[ast.def_id] params = vec(); - auto tp = metadata.tag_items_data_item_ty_param; +fn item_ty_param_count(&ebml.doc item, int this_cnum) -> uint { + let uint ty_param_count = 0u; + auto tp = metadata.tag_items_data_item_ty_param_count; for each (ebml.doc p in ebml.tagged_docs(item, tp)) { - auto ext = parse_def_id(ebml.doc_data(p)); - _vec.push[ast.def_id](params, tup(this_cnum, ext._1)); + ty_param_count = ebml.vint_at(ebml.doc_data(p), 0u)._0; } - ret params; + ret ty_param_count; } 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); } -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 data = sess.get_external_crate(external_crate_id); auto item = lookup_item(def._1, data); auto t = item_type(item, external_crate_id); - auto tps_opt; + auto tp_count; auto kind_ch = item_kind(item); auto has_ty_params = kind_has_type_params(kind_ch); if (has_ty_params) { - auto tps = item_ty_params(item, external_crate_id); - tps_opt = some[vec[ast.def_id]](tps); + tp_count = item_ty_param_count(item, external_crate_id); } 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 { diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 9410465579c..85badb1e709 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1740,8 +1740,7 @@ impure fn parse_block(parser p) -> ast.block { } impure fn parse_ty_param(parser p) -> ast.ty_param { - auto ident = parse_ident(p); - ret rec(ident=ident, id=p.next_def_id()); + ret parse_ident(p); } impure fn parse_ty_params(parser p) -> vec[ast.ty_param] { diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs index 4c46a307736..31aec74d872 100644 --- a/src/comp/middle/metadata.rs +++ b/src/comp/middle/metadata.rs @@ -29,7 +29,7 @@ const uint tag_def_id = 0x07u; const uint tag_items_data = 0x08u; const uint tag_items_data_item = 0x09u; 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_symbol = 0x0du; 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_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";} } } @@ -310,13 +310,10 @@ fn def_to_str(ast.def_id did) -> str { ret #fmt("%d:%d", did._0, did._1); } -// TODO: We need to encode the "crate numbers" somewhere for diamond imports. -fn encode_type_params(&ebml.writer ebml_w, vec[ast.ty_param] tps) { - for (ast.ty_param tp in 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); - } +fn encode_type_param_count(&ebml.writer ebml_w, vec[ast.ty_param] tps) { + ebml.start_tag(ebml_w, tag_items_data_item_ty_param_count); + ebml.write_vint(ebml_w.writer, _vec.len[ast.ty_param](tps)); + ebml.end_tag(ebml_w); } 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_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); } } @@ -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); encode_def_id(ebml_w, did); 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_symbol(cx, ebml_w, did); 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); encode_def_id(ebml_w, did); 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)); 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); encode_def_id(ebml_w, did); 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)); for (ast.variant v in variants) { 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); encode_def_id(ebml_w, odid.ctor); 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); encode_type(ebml_w, fn_ty); 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); encode_def_id(ebml_w, odid.ty); 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)); 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)) { encode_def_id(ebml_w, did); 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_symbol(cx, ebml_w, did); } diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 65045c0e604..8af9455a29a 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -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] { 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); ret some(def_wrap_other(t)); } } + + auto i = 0u; for (ast.ty_param tp in ty_params) { - if (_str.eq(tp.ident, i)) { - auto t = ast.def_ty_arg(tp.id); + if (_str.eq(tp, identifier)) { + auto t = ast.def_ty_arg(i); ret some(def_wrap_other(t)); } + i += 1u; } 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) - -> option.t[def_wrap] { + fn in_scope(&session.session sess, ast.ident identifier, &scope s, + namespace ns) -> option.t[def_wrap] { alt (s) { case (scope_crate(?c)) { - ret check_mod(i, c.node.module, ns); + ret check_mod(identifier, c.node.module, ns); } case (scope_item(?it)) { alt (it.node) { 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, _, _)) { 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); ret some(def_wrap_other(t)); } } + + auto i = 0u; for (ast.ty_param tp in ty_params) { - if (_str.eq(tp.ident, i)) { - auto t = ast.def_ty_arg(tp.id); + if (_str.eq(tp, identifier)) { + auto t = ast.def_ty_arg(i); ret some(def_wrap_other(t)); } + i += 1u; } } case (ast.item_tag(_,?variants,?ty_params,?tag_id,_)) { + auto i = 0u; for (ast.ty_param tp in ty_params) { - if (_str.eq(tp.ident, i)) { - auto t = ast.def_ty_arg(tp.id); + if (_str.eq(tp, identifier)) { + auto t = ast.def_ty_arg(i); ret some(def_wrap_other(t)); } + i += 1u; } } case (ast.item_mod(_, ?m, _)) { - ret check_mod(i, m, ns); + ret check_mod(identifier, m, ns); } case (ast.item_native_mod(_, ?m, _)) { - ret check_native_mod(i, m); + ret check_native_mod(identifier, m); } case (ast.item_ty(_, _, ?ty_params, _, _)) { + auto i = 0u; for (ast.ty_param tp in ty_params) { - if (_str.eq(tp.ident, i)) { - auto t = ast.def_ty_arg(tp.id); + if (_str.eq(tp, identifier)) { + auto t = ast.def_ty_arg(i); ret some(def_wrap_other(t)); } + i += 1u; } } case (_) { /* fall through */ } @@ -506,7 +516,7 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns) case (scope_native_item(?it)) { alt (it.node) { 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)) { alt (d.node) { case (ast.decl_local(?local)) { - if (_str.eq(local.ident, i)) { + if (_str.eq(local.ident, identifier)) { auto lc = ast.def_local(local.id); 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)) { - ret check_block(i, b.node, ns); + ret check_block(identifier, b.node, ns); } case (scope_arm(?a)) { - alt (a.index.find(i)) { + alt (a.index.find(identifier)) { case (some[ast.def_id](?did)) { auto t = ast.def_binding(did); ret some[def_wrap](def_wrap_other(t)); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2ea11e469e7..6c4620d2476 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -128,7 +128,8 @@ state type fn_ctxt = rec(ValueRef llfn, hashmap[ast.def_id, ValueRef] llobjfields, hashmap[ast.def_id, ValueRef] lllocals, 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); tag cleanup { @@ -770,14 +771,11 @@ fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef { ret typ; } -fn type_of_ty_params_opt_and_ty(@crate_ctxt ccx, ty.ty_params_opt_and_ty tpt) - -> TypeRef { +fn type_of_ty_param_count_and_ty(@crate_ctxt ccx, + ty.ty_param_count_and_ty tpt) -> TypeRef { alt (tpt._1.struct) { case (ty.ty_fn(?proto, ?inputs, ?output)) { - auto ty_params = option.get[vec[ast.def_id]](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); + auto llfnty = type_of_fn(ccx, proto, inputs, output, tpt._0); ret T_fn_pair(ccx.tn, llfnty); } 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). auto max_size = 0u; 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); // 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. 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()); 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); for (variant_info variant in variants) { // Perform type substitution on the raw argument types. let vec[@ty.t] raw_tys = variant.args; let vec[@ty.t] tys = vec(); 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); } @@ -1387,7 +1381,6 @@ fn GEP_tag(@block_ctxt cx, vec[@ty.t] ty_substs, int ix) -> 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); // 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; let vec[@ty.t] true_arg_tys = vec(); 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); if (i == ix) { 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 -// each of the ty params it uses (from the current frame), as well as a vec -// containing a def_id for each such param. This is used solely for +// each of the ty params it uses (from the current frame) and a vector of the +// indices of the ty params present in the type. This is used solely for // constructing derived tydescs. -fn linearize_ty_params(@block_ctxt cx, @ty.t t) - -> tup(vec[ast.def_id], vec[ValueRef]) { +fn linearize_ty_params(@block_ctxt cx, @ty.t t) -> + tup(vec[uint], vec[ValueRef]) { 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, mutable vec[ValueRef] vals, - mutable vec[ast.def_id] defs); + mutable vec[uint] defs); state obj folder(@rr r) { fn fold_simple_ty(@ty.t t) -> @ty.t { alt(t.struct) { case (ty.ty_param(?pid)) { let bool seen = false; - for (ast.def_id d in r.defs) { + for (uint d in r.defs) { if (d == pid) { 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 { // Is the supplied type a type param? If so, return the passed-in tydesc. alt (ty.type_param(t)) { - case (some[ast.def_id](?id)) { + case (some[uint](?id)) { check (cx.fcx.lltydescs.contains_key(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. @@ -1524,7 +1517,7 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { if (ty.count_ty_params(t) > 0u) { 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)); 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. 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); - define_tydesc(cx.fcx.ccx, t, defs); + define_tydesc(cx.fcx.ccx, t, tps); } 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. -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 gvar = info.tydesc; auto tg = make_take_glue; - auto take_glue = make_generic_glue(cx, t, info.take_glue, tg, - typaram_defs); + auto take_glue = make_generic_glue(cx, t, info.take_glue, tg, ty_params); auto dg = make_drop_glue; - auto drop_glue = make_generic_glue(cx, t, info.drop_glue, dg, - typaram_defs); + auto drop_glue = make_generic_glue(cx, t, info.drop_glue, dg, ty_params); } 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, - val_and_ty_fn helper, - vec[ast.def_id] typaram_defs) -> ValueRef { + val_and_ty_fn helper, vec[uint] ty_params) -> ValueRef { auto fcx = new_fn_ctxt(cx, llfn); auto bcx = new_top_block_ctxt(fcx); 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)); } + auto ty_param_count = _vec.len[uint](ty_params); + auto lltyparams = llvm.LLVMGetParam(llfn, 3u); - auto p = 0; - for (ast.def_id d in typaram_defs) { - auto llparam = bcx.build.GEP(lltyparams, vec(C_int(p))); + auto p = 0u; + while (p < ty_param_count) { + auto llparam = bcx.build.GEP(lltyparams, vec(C_int(p as int))); llparam = bcx.build.Load(llparam); - bcx.fcx.lltydescs.insert(d, llparam); - p += 1; + bcx.fcx.lltydescs.insert(ty_params.(p), llparam); + p += 1u; } auto llrawptr = llvm.LLVMGetParam(llfn, 4u); @@ -1928,11 +1920,6 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx, // 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); // 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 ty_params = tag_ty_params(bcx.fcx.ccx, tid); - auto i = 0u; for (variant_info variant in variants) { 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; variant_cx = rslt.bcx; - auto ty_subst = ty.substitute_ty_params( - ty_params, tps, a.ty); + auto ty_subst = + ty.substitute_type_params(tps, a.ty); auto llfld_a = 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, - ty.ty_params_opt_and_ty tpt) -> lval_result { + ty.ty_param_count_and_ty tpt) -> lval_result { auto ccx = cx.fcx.ccx; auto name = creader.get_symbol(ccx.sess, did); 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); } 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.ann ann) -> 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)); } else { // External reference. - auto tpot = tup(some[vec[ast.def_id]](tpt._0), tpt._1); - lv = trans_external_path(cx, fn_id, tpot); + lv = trans_external_path(cx, fn_id, tpt); } auto monoty; - auto tys; + let vec[@ty.t] tys; alt (ann) { case (ast.ann_none) { 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)); } 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); ret lval_generic_fn(cx, tyt, did, ann); } 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); ret lval_generic_fn(cx, tyt, did, ann); } 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); alt (v_tyt._1.struct) { 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)); } 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); 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] lllocals = 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 = 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)); } case (none[tup(TypeRef, @ty.t)]) { + auto i = 0u; for (ast.ty_param tp in ty_params) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); check (llarg as int != 0); - cx.lltydescs.insert(tp.id, llarg); + cx.lltydescs.insert(i, llarg); 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), C_int(i))); lltyparam = bcx.build.Load(lltyparam); - fcx.lltydescs.insert(p.id, lltyparam); + fcx.lltydescs.insert(i as uint, lltyparam); i += 1; } @@ -5889,7 +5875,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, bcx = body_typarams.bcx; let int i = 0; 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, vec(0, i)); bcx = capture.bcx; @@ -5951,8 +5937,10 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, fn_args, ty_params); let vec[@ty.t] ty_param_substs = vec(); + i = 0u; 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); @@ -6905,7 +6893,7 @@ fn trans_vec_append_glue(@crate_ctxt cx) { llobjfields=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](), llupvars=new_def_hash[ValueRef](), - lltydescs=new_def_hash[ValueRef](), + lltydescs=common.new_uint_hash[ValueRef](), ccx=cx); auto bcx = new_top_block_ctxt(fcx); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index b55f5156d90..6adfd3b94e8 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -57,7 +57,7 @@ tag sty { ty_obj(vec[method]); ty_var(int); // ephemeral type var ty_local(ast.def_id); // type of a local var - ty_param(ast.def_id); // fn/tag type param + ty_param(uint); // fn/tag type param ty_type; ty_native; // TODO: ty_fn_arg(@t), for a possibly-aliased function argument @@ -68,10 +68,8 @@ tag sty { type unify_handler = obj { fn resolve_local(ast.def_id id) -> @t; fn record_local(ast.def_id id, @t ty); - fn unify_expected_param(ast.def_id id, @t expected, @t actual) - -> unify_result; - fn unify_actual_param(ast.def_id id, @t expected, @t actual) - -> unify_result; + fn unify_expected_param(uint id, @t expected, @t actual) -> unify_result; + fn unify_actual_param(uint id, @t expected, @t actual) -> unify_result; }; 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 type_cache = hashmap[ast.def_id,ty_params_opt_and_ty]; +type ty_param_count_and_ty = tup(uint, @t); +type type_cache = hashmap[ast.def_id,ty_param_count_and_ty]; // Stringification @@ -248,8 +246,7 @@ fn ty_to_str(&@t typ) -> str { } case (ty_param(?id)) { - s += ""; + s += "'" + _str.unsafe_from_bytes(vec(('a' as u8) + (id as u8))); } } @@ -558,12 +555,12 @@ fn type_is_signed(@t ty) -> bool { fail; } -fn type_param(@t ty) -> option.t[ast.def_id] { +fn type_param(@t ty) -> option.t[uint] { alt (ty.struct) { - case (ty_param(?id)) { ret some[ast.def_id](id); } - case (_) { /* fall through */ } + case (ty_param(?id)) { ret some[uint](id); } + case (_) { /* fall through */ } } - ret none[ast.def_id]; + ret none[uint]; } 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 { - 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 { alt (ty.struct) { - case (ty_param(?param_id)) { - for (ast.def_id other_param_id in *param_ids) { - if (param_id._0 == other_param_id._0 && - param_id._1 == other_param_id._1) { - ret ty; + case (ty_param(?param_idx)) { + auto seen = false; + for (uint other_param_idx in *param_indices) { + if (param_idx == other_param_idx) { + seen = true; } } - *param_ids += vec(param_id); + if (!seen) { + *param_indices += vec(param_idx); + } } case (_) { /* fall through */ } } @@ -624,10 +624,10 @@ fn count_ty_params(@t ty) -> uint { } } - let vec[ast.def_id] param_ids_inner = vec(); - let @mutable vec[ast.def_id] param_ids = @mutable param_ids_inner; - fold_ty(ty_param_counter(param_ids), ty); - ret _vec.len[ast.def_id](*param_ids); + let vec[uint] v = vec(); // FIXME: typechecker botch + let @mutable vec[uint] param_indices = @mutable v; + fold_ty(ty_param_counter(param_indices), ty); + ret _vec.len[uint](*param_indices); } // Type accessors for substructures of types @@ -674,59 +674,50 @@ fn is_fn_ty(@t fty) -> bool { // Type accessors for AST nodes -// Given an item, returns the associated type as well as a list of the IDs of -// its type parameters. -type ty_params_and_ty = tup(vec[ast.def_id], @t); -fn native_item_ty(@ast.native_item it) -> ty_params_and_ty { - auto ty_params; +// Given an item, returns the associated type as well as the number of type +// parameters it has. +fn native_item_ty(@ast.native_item it) -> ty_param_count_and_ty { + auto ty_param_count; auto result_ty; alt (it.node) { 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); } } - let vec[ast.def_id] ty_param_ids = vec(); - for (ast.ty_param tp in ty_params) { - ty_param_ids += vec(tp.id); - } - ret tup(ty_param_ids, result_ty); + ret tup(ty_param_count, result_ty); } -fn item_ty(@ast.item it) -> ty_params_and_ty { - let vec[ast.ty_param] ty_params; +fn item_ty(@ast.item it) -> ty_param_count_and_ty { + auto ty_param_count; auto result_ty; alt (it.node) { case (ast.item_const(_, _, _, _, ?ann)) { - ty_params = vec(); + ty_param_count = 0u; result_ty = ann_to_type(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); } case (ast.item_mod(_, _, _)) { fail; // modules are typeless } case (ast.item_ty(_, _, ?tps, _, ?ann)) { - ty_params = tps; + ty_param_count = _vec.len[ast.ty_param](tps); result_ty = ann_to_type(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); } case (ast.item_obj(_, _, ?tps, _, ?ann)) { - ty_params = tps; + ty_param_count = _vec.len[ast.ty_param](tps); result_ty = ann_to_type(ann); } } - let vec[ast.def_id] ty_param_ids = vec(); - for (ast.ty_param tp in ty_params) { - ty_param_ids += vec(tp.id); - } - ret tup(ty_param_ids, result_ty); + ret tup(ty_param_count, result_ty); } 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 -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] { - 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 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 { bindings.insert(id, 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 { bindings.insert(id, 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 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(); - auto ty_param_ids = ty_params_and_polyty._0; - for (ast.def_id tp in ty_param_ids) { - check (bindings.contains_key(tp)); - result_tys += vec(bindings.get(tp)); + auto ty_param_count = ty_params_and_polyty._0; + auto i = 0u; + while (i < ty_param_count) { + check (bindings.contains_key(i)); + result_tys += vec(bindings.get(i)); + i += 1u; } 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 // parameter IDs to types. -fn replace_type_params(@t typ, hashmap[ast.def_id,@t] param_map) -> @t { - state obj param_replacer(hashmap[ast.def_id,@t] param_map) { +fn substitute_type_params(vec[@t] bindings, @t typ) -> @t { + state obj param_replacer(vec[@t] bindings) { fn fold_simple_ty(@t typ) -> @t { alt (typ.struct) { - case (ty_param(?param_def)) { - if (param_map.contains_key(param_def)) { - ret param_map.get(param_def); - } else { - ret typ; - } - } - case (_) { - ret typ; - } + case (ty_param(?param_index)) { ret bindings.(param_index); } + case (_) { ret typ; } } } } - auto replacer = param_replacer(param_map); + auto replacer = param_replacer(bindings); 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 { 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 // the type cache. Returns the type parameters and type. 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()) { // The item is in this crate. The caller should have added it to the // type cache already; we simply return it. @@ -1729,14 +1697,6 @@ fn lookup_item_type(session.session sess, &type_cache cache, 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: // mode: rust diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 663c0bb90ee..5c512e7eac5 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -22,7 +22,7 @@ import middle.ty.plain_ty; import middle.ty.ty_to_str; import middle.ty.type_is_integral; 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 std._str; @@ -59,7 +59,7 @@ type fn_ctxt = rec(@ty.t ret_ty, @crate_ctxt ccx); // 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. fn triv_ann(@ty.t t) -> ann { @@ -75,8 +75,7 @@ fn boring_ann() -> ann { // Replaces parameter types inside a type with type variables. fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { state obj ty_generalizer(@crate_ctxt cx, - @hashmap[ast.def_id,@ty.t] - ty_params_to_ty_vars) { + @hashmap[uint,@ty.t] ty_params_to_ty_vars) { fn fold_simple_ty(@ty.t t) -> @ty.t { alt (t.struct) { 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); } @@ -101,57 +100,39 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { // expression. fn substitute_ty_params(&@crate_ctxt ccx, @ty.t typ, - vec[ast.def_id] ty_params, + uint ty_param_count, vec[@ty.t] supplied, &span sp) -> @ty.t { - state obj ty_substituter(@crate_ctxt ccx, - vec[ast.def_id] ty_params, - vec[@ty.t] supplied) { + state obj ty_substituter(@crate_ctxt ccx, vec[@ty.t] supplied) { fn fold_simple_ty(@ty.t typ) -> @ty.t { alt (typ.struct) { - case (ty.ty_param(?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 (ty.ty_param(?pid)) { ret supplied.(pid); } case (_) { ret typ; } } } } - auto ty_param_len = _vec.len[ast.def_id](ty_params); auto supplied_len = _vec.len[@ty.t](supplied); - if (ty_param_len != supplied_len) { - ccx.sess.span_err(sp, "expected " + _uint.to_str(ty_param_len, 10u) + + if (ty_param_count != supplied_len) { + ccx.sess.span_err(sp, "expected " + + _uint.to_str(ty_param_count, 10u) + " type parameter(s) but found " + _uint.to_str(supplied_len, 10u) + " parameter(s)"); fail; } - auto substituter = ty_substituter(ccx, ty_params, supplied); + auto substituter = ty_substituter(ccx, supplied); ret ty.fold_ty(substituter, typ); } -// Returns the type parameters and the type for the given definition. -fn ty_params_and_ty_for_def(@fn_ctxt fcx, &ast.def defn) - -> ty_params_opt_and_ty { +// Returns the type parameter count and the type for the given definition. +fn ty_param_count_and_ty_for_def(@fn_ctxt fcx, &ast.def defn) + -> ty_param_count_and_ty { alt (defn) { case (ast.def_arg(?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)) { 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 (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)) { 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)) { 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)) { 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)) { 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(_)) { // Hopefully part of a path. // 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(_)) { @@ -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 -// type parameters and type. -fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_params_opt_and_ty tpt, +// number of type parameters and type. +fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_param_count_and_ty tpt, &span sp) -> ast.ann { - auto ty_params = tpt._0; + auto ty_param_count = tpt._0; auto t = tpt._1; 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); - alt (ty_params) { - case (none[vec[ast.def_id]]) { - fcx.ccx.sess.span_err(sp, "this kind of item may not take " + - "type parameters"); - fail; - } - case (some[vec[ast.def_id]](?tps)) { - t = substitute_ty_params(fcx.ccx, t, tps, ty_substs, sp); - } + if (ty_param_count == 0u) { + fcx.ccx.sess.span_err(sp, "this item does not take type " + + "parameters"); + fail; } + + t = substitute_ty_params(fcx.ccx, t, ty_param_count, ty_substs, sp); } else { ty_substs_opt = none[vec[@ty.t]]; - alt (ty_params) { - case (none[vec[ast.def_id]]) { /* nothing */ } - case (some[vec[ast.def_id]](_)) { - // We will acquire the type parameters through - // unification. - t = generalize_ty(fcx.ccx, t); - } + if (ty_param_count > 0u) { + // We will acquire the type parameters through unification. + t = generalize_ty(fcx.ccx, t); } } 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 // notion of a type. `getter` is a function that returns the type // 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 // "foo = int" like OCaml? 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](); - for each (uint i in _uint.range(0u, num_type_args)) { - 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); - } + if (params_opt_and_ty._0 == 0u) { + ret params_opt_and_ty._1; } + + // 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; @@ -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 // ast_ty_to_ty. 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); } 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 // 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, ty.type_cache type_cache, 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.proto proto, 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 output_ty = convert(decl.output); 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 tpt = tup(params_opt, t_fn); + auto ty_param_count = _vec.len[ast.ty_param](ty_params); + auto tpt = tup(ty_param_count, t_fn); type_cache.insert(def_id, 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.native_abi abi, 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 output_ty = convert(decl.output); 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 tpt = tup(params_opt, t_fn); + auto ty_param_count = _vec.len[ast.ty_param](ty_params); + auto tpt = tup(ty_param_count, t_fn); type_cache.insert(def_id, tpt); ret tpt; } @@ -470,7 +402,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn getter(session.session sess, @ty_item_table id_to_ty_item, 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()) { // 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, &ast.ident id, &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 methods = _vec.map[@ast.method,method](f, obj_info.methods); auto t_obj = @rec(struct=ty.ty_obj(ty.sort_methods(methods)), cname=some[str](id)); - auto params = ty_params_to_def_ids(ty_params); - auto params_opt = some[vec[ast.def_id]](params); - ret tup(params_opt, t_obj); + auto ty_param_count = _vec.len[ast.ty_param](ty_params); + ret tup(ty_param_count, t_obj); } 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.def_id obj_ty_id, 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, id, obj_info, ty_params); 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, @ty_item_table id_to_ty_item, 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 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, _)) { 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, _)) { @@ -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 // call to resolve any named types. auto typ = convert(ty); - auto params = ty_params_to_def_ids(tps); - auto params_opt = some[vec[ast.def_id]](params); - auto tpt = tup(params_opt, typ); + auto ty_param_count = _vec.len[ast.ty_param](tps); + auto tpt = tup(ty_param_count, typ); type_cache.insert(def_id, tpt); ret tpt; } @@ -607,14 +537,17 @@ fn collect_item_types(session.session sess, @ast.crate crate) case (ast.item_tag(_, _, ?tps, ?def_id, _)) { // Create a new generic polytype. let vec[@ty.t] subtys = vec(); + + auto i = 0u; 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 params = ty_params_to_def_ids(tps); - auto params_opt = some[vec[ast.def_id]](params); - auto tpt = tup(params_opt, t); + auto ty_param_count = _vec.len[ast.ty_param](tps); + auto tpt = tup(ty_param_count, t); type_cache.insert(def_id, 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.type_cache type_cache, @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) { case (ast.native_item_fn(?ident, ?lname, ?fn_decl, ?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 tpt = tup(none[vec[ast.def_id]], t); + auto tpt = tup(0u, t); type_cache.insert(def_id, 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. let vec[@ty.t] ty_param_tys = vec(); + auto i = 0u; 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 params_opt = some[vec[ast.def_id]](params); + auto ty_param_count = _vec.len[ast.ty_param](ty_params); for (ast.variant variant in variants) { // 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)); } - auto tpt = tup(params_opt, result_ty); + auto tpt = tup(ty_param_count, result_ty); type_cache.insert(variant.node.id, tpt); auto variant_t = rec(ann=triv_ann(result_ty) 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. - 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, @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) { 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 { alt (actual.struct) { case (ty.ty_param(?actual_id)) { - if (id._0 == actual_id._0 && id._1 == actual_id._1) { - ret ty.ures_ok(expected); - } + if (id == actual_id) { ret ty.ures_ok(expected); } } case (_) { /* fall through */ } } 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 { alt (expected.struct) { case (ty.ty_param(?expected_id)) { - if (id._0 == expected_id._0 && id._1 == expected_id._1) { - ret ty.ures_ok(actual); - } + if (id == expected_id) { ret ty.ures_ok(actual); } } case (_) { /* fall through */ } } @@ -1087,7 +1017,7 @@ mod Pushdown { // Figure out the type parameters of the tag. 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); auto ty_params = tpt._0; @@ -1367,15 +1297,10 @@ mod Pushdown { alt (tps_opt) { case (none[vec[@ty.t]]) { auto defn = option.get[ast.def](d); - alt (ty_params_for_item(fcx.ccx, defn)) { - case (none[ty.ty_params_and_ty]) { - ty_params_opt = none[vec[@ty.t]]; - } - case (some[ty.ty_params_and_ty](?tpt)) { - auto tps = ty.resolve_ty_params(tpt, t); - ty_params_opt = some[vec[@ty.t]](tps); - } - } + auto tpt = + ty_param_count_and_ty_for_def(fcx, defn); + auto tps = ty.resolve_ty_params(tpt, t); + ty_params_opt = some[vec[@ty.t]](tps); } case (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); check (defopt != none[ast.def]); 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); ret @fold.respan[ast.expr_](expr.span, 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; alt (this_obj_id) { case (some[ast.def_id](?def_id)) { - auto this_obj_tpt = fcx.ccx.type_cache.find(def_id); - alt (this_obj_tpt) { - case (some[ty_params_opt_and_ty](?tpt)) { - this_obj_ty = tpt._1; - } - case (_) { fail; } - } + this_obj_ty = ty.lookup_item_type(fcx.ccx.sess, + fcx.ccx.type_cache, def_id)._1; } case (_) { fail; } } diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index dd36f57bccc..6aee29d7241 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -796,7 +796,7 @@ impure fn print_type_params(ps s, vec[ast.ty_param] params) { if (_vec.len[ast.ty_param](params) > 0u) { wrd(s.s, "["); impure fn printParam(ps s, &ast.ty_param param) { - wrd(s.s, param.ident); + wrd(s.s, param); } auto f = printParam; commasep[ast.ty_param](s, params, f);