authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-06 17:46:02+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-07 11:04:02+03:00
log4a6cc1c602a08ddff6c498d8c37919c5c0c842f0
tree69b38e06390a41c3140a61268222a256ea814c09
parent2315e1b41073a8d6a7f7fe3deb98ec98e45d72f6

Sema: allow equality comparisons between error unions and error sets

Closes #1302

3 files changed, 33 insertions(+), 10 deletions(-)

src/Sema.zig+12
......@@ -7622,6 +7622,10 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
76227622 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
76237623 const src = inst_data.src();
76247624 const operand = try sema.resolveInst(inst_data.operand);
7625 return sema.analyzeErrUnionCode(block, src, operand);
7626}
7627
7628fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref {
76257629 const operand_ty = sema.typeOf(operand);
76267630 if (operand_ty.zigTypeTag() != .ErrorUnion) {
76277631 return sema.fail(block, src, "expected error union type, found '{}'", .{
......@@ -14129,6 +14133,14 @@ fn analyzeCmp(
1412914133 // numeric types.
1413014134 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
1413114135 }
14136 if (is_equality_cmp and lhs_ty.zigTypeTag() == .ErrorUnion and rhs_ty.zigTypeTag() == .ErrorSet) {
14137 const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs);
14138 return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src);
14139 }
14140 if (is_equality_cmp and lhs_ty.zigTypeTag() == .ErrorSet and rhs_ty.zigTypeTag() == .ErrorUnion) {
14141 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);
14142 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);
14143 }
1413214144 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1413314145 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
1413414146 if (!resolved_type.isSelfComparable(is_equality_cmp)) {
test/behavior/error.zig+21
......@@ -809,3 +809,24 @@ test "alignment of wrapping an error union payload" {
809809 };
810810 try expect((S.foo() catch unreachable).x == 1234);
811811}
812
813test "compare error union and error set" {
814 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
816
817 var a: anyerror = error.Foo;
818 var b: anyerror!u32 = error.Bar;
819
820 try expect(a != b);
821 try expect(b != a);
822
823 b = error.Foo;
824
825 try expect(a == b);
826 try expect(b == a);
827
828 b = 2;
829
830 try expect(a != b);
831 try expect(b != a);
832}
test/cases/compile_errors/comparison_with_error_union_and_error_value.zig deleted-10
......@@ -1,10 +0,0 @@
1export fn entry() void {
2 var number_or_error: anyerror!i32 = error.SomethingAwful;
3 _ = number_or_error == error.SomethingAwful;
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :3:25: error: operator == not allowed for type 'anyerror!i32'