authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-22 13:53:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-22 13:53:10-07:00
logb23f10b42403406f40158ec11de95a3f80ce5879
treefa3a9e848283e73eb4774d90ee7994192251e4a2
parent0d422ce342977b56247ec95aa0bd58045ee8b66b

Sema: fix comptime coercion of payload to error union


2 files changed, 28 insertions(+), 23 deletions(-)

src/Sema.zig+28-19
...@@ -14859,21 +14859,25 @@ fn coerce(...@@ -14859,21 +14859,25 @@ fn coerce(
14859 inst_ty.errorUnionPayload(),14859 inst_ty.errorUnionPayload(),
14860 inst_val.castTag(.eu_payload).?.data,14860 inst_val.castTag(.eu_payload).?.data,
14861 );14861 );
14862 return sema.wrapErrorUnion(block, dest_ty, payload, inst_src);14862 return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src);
14863 },14863 },
14864 else => {14864 else => {
14865 const error_set = try sema.addConstant(14865 const error_set = try sema.addConstant(
14866 inst_ty.errorUnionSet(),14866 inst_ty.errorUnionSet(),
14867 inst_val,14867 inst_val,
14868 );14868 );
14869 return sema.wrapErrorUnion(block, dest_ty, error_set, inst_src);14869 return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src);
14870 },14870 },
14871 }14871 }
14872 }14872 }
14873 },14873 },
14874 .ErrorSet => {
14875 // E to E!T
14876 return sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src);
14877 },
14874 else => {14878 else => {
14875 // T to E!T or E to E!T14879 // T to E!T
14876 return sema.wrapErrorUnion(block, dest_ty, inst, inst_src);14880 return sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src);
14877 },14881 },
14878 },14882 },
14879 .Union => switch (inst_ty.zigTypeTag()) {14883 .Union => switch (inst_ty.zigTypeTag()) {
...@@ -16688,7 +16692,24 @@ fn wrapOptional(...@@ -16688,7 +16692,24 @@ fn wrapOptional(
16688 return block.addTyOp(.wrap_optional, dest_ty, inst);16692 return block.addTyOp(.wrap_optional, dest_ty, inst);
16689}16693}
1669016694
16691fn wrapErrorUnion(16695fn wrapErrorUnionPayload(
16696 sema: *Sema,
16697 block: *Block,
16698 dest_ty: Type,
16699 inst: Air.Inst.Ref,
16700 inst_src: LazySrcLoc,
16701) !Air.Inst.Ref {
16702 const dest_payload_ty = dest_ty.errorUnionPayload();
16703 const coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);
16704 if (try sema.resolveMaybeUndefVal(block, inst_src, coerced)) |val| {
16705 if (val.isUndef()) return sema.addConstUndef(dest_ty);
16706 return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
16707 }
16708 try sema.requireRuntimeBlock(block, inst_src);
16709 return block.addTyOp(.wrap_errunion_payload, dest_ty, coerced);
16710}
16711
16712fn wrapErrorUnionSet(
16692 sema: *Sema,16713 sema: *Sema,
16693 block: *Block,16714 block: *Block,
16694 dest_ty: Type,16715 dest_ty: Type,
...@@ -16697,12 +16718,7 @@ fn wrapErrorUnion(...@@ -16697,12 +16718,7 @@ fn wrapErrorUnion(
16697) !Air.Inst.Ref {16718) !Air.Inst.Ref {
16698 const inst_ty = sema.typeOf(inst);16719 const inst_ty = sema.typeOf(inst);
16699 const dest_err_set_ty = dest_ty.errorUnionSet();16720 const dest_err_set_ty = dest_ty.errorUnionSet();
16700 const dest_payload_ty = dest_ty.errorUnionPayload();
16701 if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {16721 if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
16702 if (inst_ty.zigTypeTag() != .ErrorSet) {
16703 _ = try sema.coerce(block, dest_payload_ty, inst, inst_src);
16704 return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
16705 }
16706 switch (dest_err_set_ty.tag()) {16722 switch (dest_err_set_ty.tag()) {
16707 .anyerror => {},16723 .anyerror => {},
16708 .error_set_single => ok: {16724 .error_set_single => ok: {
...@@ -16739,15 +16755,8 @@ fn wrapErrorUnion(...@@ -16739,15 +16755,8 @@ fn wrapErrorUnion(
16739 }16755 }
1674016756
16741 try sema.requireRuntimeBlock(block, inst_src);16757 try sema.requireRuntimeBlock(block, inst_src);
1674216758 const coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src);
16743 // we are coercing from E to E!T16759 return block.addTyOp(.wrap_errunion_err, dest_ty, coerced);
16744 if (inst_ty.zigTypeTag() == .ErrorSet) {
16745 var coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src);
16746 return block.addTyOp(.wrap_errunion_err, dest_ty, coerced);
16747 } else {
16748 var coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);
16749 return block.addTyOp(.wrap_errunion_payload, dest_ty, coerced);
16750 }
16751}16760}
1675216761
16753fn unionToTag(16762fn unionToTag(
test/behavior/enum.zig-4
...@@ -907,8 +907,6 @@ test "enum literal casting to tagged union" {...@@ -907,8 +907,6 @@ test "enum literal casting to tagged union" {
907const Bar = enum { A, B, C, D };907const Bar = enum { A, B, C, D };
908908
909test "enum literal casting to error union with payload enum" {909test "enum literal casting to error union with payload enum" {
910 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
911
912 var bar: error{B}!Bar = undefined;910 var bar: error{B}!Bar = undefined;
913 bar = .B; // should never cast to the error set911 bar = .B; // should never cast to the error set
914912
...@@ -932,8 +930,6 @@ test "exporting enum type and value" {...@@ -932,8 +930,6 @@ test "exporting enum type and value" {
932}930}
933931
934test "constant enum initialization with differing sizes" {932test "constant enum initialization with differing sizes" {
935 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
936
937 try test3_1(test3_foo);933 try test3_1(test3_foo);
938 try test3_2(test3_bar);934 try test3_2(test3_bar);
939}935}