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_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; }

View file

@ -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 {

View file

@ -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] {

View file

@ -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)));
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);
}

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] {
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));

View file

@ -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);

View file

@ -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 += "<P" + util.common.istr(id._0) + ":" +
util.common.istr(id._1) + ">";
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 (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

View file

@ -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");
if (ty_param_count == 0u) {
fcx.ccx.sess.span_err(sp, "this item does not take type " +
"parameters");
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 {
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.
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,16 +1297,11 @@ 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 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; }
}

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) {
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);