aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2023-10-02 15:44:50 +0300
committerAndrew Kelley <andrew@ziglang.org>2023-10-03 00:45:48 -0700
commit0bdbd3e235daee64caf1f99e5b9d7b62f4c5c484 (patch)
tree374a407a0db101d2d17fc358e4b0d30dbc8b1c9d /src/Sema.zig
parentc9c3ee704c45efe0e19bd02c08f51c7513268e76 (diff)
downloadzig-0bdbd3e235daee64caf1f99e5b9d7b62f4c5c484.tar.gz
zig-0bdbd3e235daee64caf1f99e5b9d7b62f4c5c484.zip
Sema: fix issues in `@errorCast` with error unions
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig21
1 files changed, 14 insertions, 7 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 096ebb0589..27dd7221fc 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -21771,10 +21771,10 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
// operand must be defined since it can be an invalid error value
const maybe_operand_val = try sema.resolveDefinedValue(block, operand_src, operand);
- if (disjoint: {
+ const disjoint = disjoint: {
// Try avoiding resolving inferred error sets if we can
- if (!dest_ty.isAnyError(mod) and dest_ty.errorSetNames(mod).len == 0) break :disjoint true;
- if (!operand_ty.isAnyError(mod) and operand_ty.errorSetNames(mod).len == 0) break :disjoint true;
+ if (!dest_ty.isAnyError(mod) and dest_ty.errorSetIsEmpty(mod)) break :disjoint true;
+ if (!operand_ty.isAnyError(mod) and operand_ty.errorSetIsEmpty(mod)) break :disjoint true;
if (dest_ty.isAnyError(mod)) break :disjoint false;
if (operand_ty.isAnyError(mod)) break :disjoint false;
for (dest_ty.errorSetNames(mod)) |dest_err_name| {
@@ -21796,7 +21796,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
}
break :disjoint true;
- }) {
+ };
+ if (disjoint and dest_tag != .ErrorUnion) {
const msg = msg: {
const msg = try sema.errMsg(
block,
@@ -21850,10 +21851,16 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
.int = .{ .ty = .u16_type, .storage = .{ .u64 = 0 } },
}));
- const has_value = try block.addTyOp(.error_set_has_value, dest_ty, err_code);
const is_zero = try block.addBinOp(.cmp_eq, err_int, zero_u16);
- const ok = try block.addBinOp(.bit_or, has_value, is_zero);
- try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
+ if (disjoint) {
+ // Error must be zero.
+ try sema.addSafetyCheck(block, src, is_zero, .invalid_error_code);
+ } else {
+ // Error must be in destination set or zero.
+ const has_value = try block.addTyOp(.error_set_has_value, dest_ty, err_code);
+ const ok = try block.addBinOp(.bit_or, has_value, is_zero);
+ try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
+ }
} else {
const err_int_inst = try block.addBitCast(Type.err_int, operand);
const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);