authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-02-05 20:13:56+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-02-05 20:13:56+00:00
logcac814cf58ca65ffd8081dca6f2f5b26d822ef5d
treea47d2a1e449630d66526acbb73e4714cffee52fc
parent9ba9f457be13c0c32981e94cf75ba7ea6619d92f
signaturelock-open Commit is signed but in an unrecognized format.

Sema: fix comparison between error set and comptime-known error union

Resolves: #20613

2 files changed, 19 insertions(+), 1 deletions(-)

src/Sema.zig+8-1
...@@ -9145,6 +9145,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -9145,6 +9145,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
9145 return sema.analyzeErrUnionCode(block, src, operand);9145 return sema.analyzeErrUnionCode(block, src, operand);
9146}9146}
91479147
9148/// If `operand` is comptime-known, asserts that it is an error value rather than a payload value.
9148fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref {9149fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref {
9149 const pt = sema.pt;9150 const pt = sema.pt;
9150 const zcu = pt.zcu;9151 const zcu = pt.zcu;
...@@ -17599,10 +17600,16 @@ fn analyzeCmp(...@@ -17599,10 +17600,16 @@ fn analyzeCmp(
17599 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);17600 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
17600 }17601 }
17601 if (is_equality_cmp and lhs_ty.zigTypeTag(zcu) == .error_union and rhs_ty.zigTypeTag(zcu) == .error_set) {17602 if (is_equality_cmp and lhs_ty.zigTypeTag(zcu) == .error_union and rhs_ty.zigTypeTag(zcu) == .error_set) {
17603 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
17604 if (lhs_val.errorUnionIsPayload(zcu)) return .bool_false;
17605 }
17602 const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs);17606 const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs);
17603 return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src);17607 return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src);
17604 }17608 }
17605 if (is_equality_cmp and lhs_ty.zigTypeTag(zcu) == .error_set and rhs_ty.zigTypeTag(zcu) == .error_union) {17609 if (is_equality_cmp and lhs_ty.zigTypeTag(zcu) == .error_set and rhs_ty.zigTypeTag(zcu) == .error_union) {
17610 if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| {
17611 if (rhs_val.errorUnionIsPayload(zcu)) return .bool_false;
17612 }
17606 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);17613 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);
17607 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);17614 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);
17608 }17615 }
...@@ -23254,7 +23261,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -23254,7 +23261,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
23254 zcu.backendSupportsFeature(.error_set_has_value))23261 zcu.backendSupportsFeature(.error_set_has_value))
23255 {23262 {
23256 if (dest_tag == .error_union) {23263 if (dest_tag == .error_union) {
23257 const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);23264 const err_code = try block.addTyOp(.unwrap_errunion_err, operand_ty, operand);
23258 const err_int = try block.addBitCast(err_int_ty, err_code);23265 const err_int = try block.addBitCast(err_int_ty, err_code);
23259 const zero_err = try pt.intRef(try pt.errorIntType(), 0);23266 const zero_err = try pt.intRef(try pt.errorIntType(), 0);
2326023267
test/behavior/error.zig+11
...@@ -1100,3 +1100,14 @@ test "return error union with i65" {...@@ -1100,3 +1100,14 @@ test "return error union with i65" {
1100fn add(x: i65, y: i65) anyerror!i65 {1100fn add(x: i65, y: i65) anyerror!i65 {
1101 return x + y;1101 return x + y;
1102}1102}
1103
1104test "compare error union to error set" {
1105 const S = struct {
1106 fn doTheTest(val: error{Foo}!i32) !void {
1107 if (error.Foo == val) return error.Unexpected;
1108 if (val == error.Foo) return error.Unexpected;
1109 }
1110 };
1111 try S.doTheTest(0);
1112 try comptime S.doTheTest(0);
1113}