diff --git a/src/Makefile b/src/Makefile index 2c35d07f649..70e2330e532 100644 --- a/src/Makefile +++ b/src/Makefile @@ -453,7 +453,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ foreach-put-structured.rs \ foreach-simple-outer-slot.rs \ generic-iter-frame.rs \ - generic-tag-values.rs \ iter-range.rs \ iter-ret.rs \ lazychan.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3c5253ff60e..00e7e6d839a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1185,8 +1185,16 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, // This function uses GEP_tup_like() above and automatically performs casts as // appropriate. @llblobptr is the data part of a tag value; its actual type is // meaningless, as it will be cast away. -fn GEP_tag(@block_ctxt cx, ValueRef llblobptr, &ast.variant variant, int ix) +fn GEP_tag(@block_ctxt cx, + ValueRef llblobptr, + &ast.def_id tag_id, + &ast.def_id variant_id, + 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. // Separately, store the type of the element we're interested in. auto arg_tys = arg_tys_of_fn(variant.ann); @@ -1194,9 +1202,10 @@ fn GEP_tag(@block_ctxt cx, ValueRef llblobptr, &ast.variant variant, int ix) auto i = 0; let vec[@ty.t] true_arg_tys = vec(); for (ty.arg a in arg_tys) { - true_arg_tys += vec(a.ty); + auto arg_ty = ty.substitute_ty_params(ty_params, ty_substs, a.ty); + true_arg_tys += vec(arg_ty); if (i == ix) { - elem_ty = a.ty; + elem_ty = arg_ty; } i += 1; @@ -2283,6 +2292,24 @@ fn node_ann_type(@crate_ctxt cx, &ast.ann a) -> @ty.t { } } +fn node_ann_ty_params(&ast.ann a) -> vec[@ty.t] { + alt (a) { + case (ast.ann_none) { + log "missing type annotation"; + fail; + } + case (ast.ann_type(_, ?tps_opt)) { + alt (tps_opt) { + case (none[vec[@ty.t]]) { + log "type annotation has no ty params"; + fail; + } + case (some[vec[@ty.t]](?tps)) { ret tps; } + } + } + } +} + fn node_type(@crate_ctxt cx, &ast.ann a) -> TypeRef { ret type_of(cx, node_ann_type(cx, a)); } @@ -2981,13 +3008,15 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, C_int(variant_tag)); cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); + auto ty_params = node_ann_ty_params(ann); + if (_vec.len[@ast.pat](subpats) > 0u) { auto llblobptr = matched_cx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); auto i = 0; for (@ast.pat subpat in subpats) { - auto rslt = GEP_tag(matched_cx, llblobptr, variants.(i), - i); + auto rslt = GEP_tag(matched_cx, llblobptr, vdef._0, + vdef._1, ty_params, i); auto llsubvalptr = rslt.val; matched_cx = rslt.bcx; @@ -3025,7 +3054,7 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval) ret copy_ty(bcx, INIT, dst, llval, ty); } - case (ast.pat_tag(_, ?subpats, ?vdef_opt, _)) { + case (ast.pat_tag(_, ?subpats, ?vdef_opt, ?ann)) { if (_vec.len[@ast.pat](subpats) == 0u) { ret res(cx, llval); } // Get the appropriate variant for this tag. @@ -3036,10 +3065,13 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval) T_opaque_tag_ptr(cx.fcx.ccx.tn)); auto llblobptr = cx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); + auto ty_param_substs = node_ann_ty_params(ann); + auto this_cx = cx; auto i = 0; for (@ast.pat subpat in subpats) { - auto rslt = GEP_tag(this_cx, llblobptr, variant, i); + auto rslt = GEP_tag(this_cx, llblobptr, vdef._0, vdef._1, + ty_param_substs, i); this_cx = rslt.bcx; auto llsubvalptr = rslt.val; @@ -4926,6 +4958,11 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); + let vec[@ty.t] ty_param_substs = vec(); + for (ast.ty_param tp in ty_params) { + ty_param_substs += vec(plain_ty(ty.ty_param(tp.id))); + } + auto bcx = new_top_block_ctxt(fcx); auto arg_tys = arg_tys_of_fn(variant.ann); @@ -4944,7 +4981,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, i = 0u; for (ast.variant_arg va in variant.args) { - auto rslt = GEP_tag(bcx, llblobptr, variant, i as int); + auto rslt = GEP_tag(bcx, llblobptr, tag_id, variant.id, + ty_param_substs, i as int); bcx = rslt.bcx; auto lldestptr = rslt.val; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index a0adf55a784..7dfe918c065 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1085,6 +1085,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { fail; } } + auto tps_opt = some[vec[@ty.t]](ty_param_substs); // The type of the tag isn't enough; we also have to get the type // of the variant, which is either a tag type in the case of @@ -1100,7 +1101,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { // Nullary tag variant. check (subpats_len == 0u); p_1 = ast.pat_tag(id, subpats, vdef_opt, - ast.ann_type(t, none[vec[@ty.t]])); + ast.ann_type(t, tps_opt)); } case (ty.ty_fn(_, ?args, ?tag_ty)) { // N-ary tag variant. @@ -1115,7 +1116,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { i += 1u; } p_1 = ast.pat_tag(id, new_subpats, vdef_opt, - ast.ann_type(tag_ty, none[vec[@ty.t]])); + ast.ann_type(tag_ty, tps_opt)); } } }