From 19b2850388f634b500e612d8f24bbcb8c0fa2f3c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 24 Feb 2011 19:24:12 -0800 Subject: rustc: Perform type parameter substitutions when emitting glue for generic tags. Un-XFAIL generic-tag.rs. --- src/comp/middle/trans.rs | 21 +++++++++++++-------- src/comp/middle/ty.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- src/comp/middle/typeck.rs | 23 +---------------------- 3 files changed, 56 insertions(+), 31 deletions(-) (limited to 'src/comp') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a3a1d83f..467aaa0d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1,3 +1,4 @@ +import std._int; import std._str; import std._uint; import std._vec; @@ -61,7 +62,8 @@ type glue_fns = rec(ValueRef activate_glue, tag arity { nullary; n_ary; } type tag_info = rec(type_handle th, mutable vec[tup(ast.def_id,arity)] variants, - mutable uint size); + mutable uint size, + vec[ast.ty_param] ty_params); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -1498,9 +1500,7 @@ fn iter_structural_ty(@block_ctxt cx, i += 1; } } - case (ty.ty_tag(?tid, _)) { - // TODO: type params! - + case (ty.ty_tag(?tid, ?tps)) { check (cx.fcx.ccx.tags.contains_key(tid)); auto info = cx.fcx.ccx.tags.get(tid); auto n_variants = _vec.len[tup(ast.def_id,arity)](info.variants); @@ -1559,11 +1559,15 @@ fn iter_structural_ty(@block_ctxt cx, auto llfldp = variant_cx.build.GEP(llvarp, v); + auto ty_subst = ty.substitute_ty_params( + info.ty_params, tps, a.ty); + auto llfld = load_scalar_or_boxed(variant_cx, - llfldp, a.ty); + llfldp, + ty_subst); - auto res = f(variant_cx, llfld, a.ty); + auto res = f(variant_cx, llfld, ty_subst); variant_cx = res.bcx; j += 1u; } @@ -4433,13 +4437,14 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { cx.items.insert(mid, i); } - case (ast.item_tag(_, ?variants, _, ?tag_id)) { + case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); let vec[tup(ast.def_id,arity)] variant_info = vec(); cx.tags.insert(tag_id, @rec(th=mk_type_handle(), mutable variants=variant_info, - mutable size=0u)); + mutable size=0u, + ty_params=tps)); cx.items.insert(tag_id, i); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 5535879e..02a7ffc2 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1450,7 +1450,7 @@ fn type_err_to_str(&ty.type_err err) -> str { } } -// Type parameter resolution, used in translation +// Type parameter resolution, used in translation and typechecking fn resolve_ty_params(ty_params_and_ty ty_params_and_polyty, @t monoty) -> vec[@t] { @@ -1492,6 +1492,47 @@ fn resolve_ty_params(ty_params_and_ty ty_params_and_polyty, ret result_tys; } +// 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 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; + } + } + } + } + auto replacer = param_replacer(param_map); + 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.ty_param] ty_params, vec[@t] bound, @t ty) + -> @t { + auto ty_param_len = _vec.len[ast.ty_param](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).id, bound.(i)); + i += 1u; + } + + ret replace_type_params(ty, bindings); +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 0d583c5e..40fd0f15 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -147,27 +147,6 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { ret rec(mode=arg.mode, ty=ast_ty_to_ty(getter, arg.ty)); } - fn replace_type_params(@ty.t t, ty_table param_map) -> @ty.t { - state obj param_replacer(ty_table param_map) { - fn fold_simple_ty(@ty.t t) -> @ty.t { - alt (t.struct) { - case (ty.ty_param(?param_def)) { - if (param_map.contains_key(param_def)) { - ret param_map.get(param_def); - } else { - ret t; - } - } - case (_) { - ret t; - } - } - } - } - auto replacer = param_replacer(param_map); - ret ty.fold_ty(replacer, t); - } - fn instantiate(ty_getter getter, ast.def_id id, vec[@ast.ty] args) -> @ty.t { // TODO: maybe record cname chains so we can do @@ -183,7 +162,7 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { auto param = params.(i); param_map.insert(param.id, ast_ty_to_ty(getter, arg)); } - ret replace_type_params(ty_and_params.ty, param_map); + ret ty.replace_type_params(ty_and_params.ty, param_map); } auto mut = ast.imm; -- cgit v1.2.3