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(
1485914859 inst_ty.errorUnionPayload(),
1486014860 inst_val.castTag(.eu_payload).?.data,
1486114861 );
14862 return sema.wrapErrorUnion(block, dest_ty, payload, inst_src);
14862 return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src);
1486314863 },
1486414864 else => {
1486514865 const error_set = try sema.addConstant(
1486614866 inst_ty.errorUnionSet(),
1486714867 inst_val,
1486814868 );
14869 return sema.wrapErrorUnion(block, dest_ty, error_set, inst_src);
14869 return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src);
1487014870 },
1487114871 }
1487214872 }
1487314873 },
14874 .ErrorSet => {
14875 // E to E!T
14876 return sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src);
14877 },
1487414878 else => {
14875 // T to E!T or E to E!T
14876 return sema.wrapErrorUnion(block, dest_ty, inst, inst_src);
14879 // T to E!T
14880 return sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src);
1487714881 },
1487814882 },
1487914883 .Union => switch (inst_ty.zigTypeTag()) {
......@@ -16688,7 +16692,24 @@ fn wrapOptional(
1668816692 return block.addTyOp(.wrap_optional, dest_ty, inst);
1668916693}
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(
1669216713 sema: *Sema,
1669316714 block: *Block,
1669416715 dest_ty: Type,
......@@ -16697,12 +16718,7 @@ fn wrapErrorUnion(
1669716718) !Air.Inst.Ref {
1669816719 const inst_ty = sema.typeOf(inst);
1669916720 const dest_err_set_ty = dest_ty.errorUnionSet();
16700 const dest_payload_ty = dest_ty.errorUnionPayload();
1670116721 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 }
1670616722 switch (dest_err_set_ty.tag()) {
1670716723 .anyerror => {},
1670816724 .error_set_single => ok: {
......@@ -16739,15 +16755,8 @@ fn wrapErrorUnion(
1673916755 }
1674016756
1674116757 try sema.requireRuntimeBlock(block, inst_src);
16742
16743 // we are coercing from E to E!T
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 }
16758 const coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src);
16759 return block.addTyOp(.wrap_errunion_err, dest_ty, coerced);
1675116760}
1675216761
1675316762fn unionToTag(
test/behavior/enum.zig-4
......@@ -907,8 +907,6 @@ test "enum literal casting to tagged union" {
907907const Bar = enum { A, B, C, D };
908908
909909test "enum literal casting to error union with payload enum" {
910 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
911
912910 var bar: error{B}!Bar = undefined;
913911 bar = .B; // should never cast to the error set
914912
......@@ -932,8 +930,6 @@ test "exporting enum type and value" {
932930}
933931
934932test "constant enum initialization with differing sizes" {
935 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
936
937933 try test3_1(test3_foo);
938934 try test3_2(test3_bar);
939935}