diff options
| author | Veikka Tuominen <git@vexu.eu> | 2023-10-02 15:44:50 +0300 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-10-03 00:45:48 -0700 |
| commit | 0bdbd3e235daee64caf1f99e5b9d7b62f4c5c484 (patch) | |
| tree | 374a407a0db101d2d17fc358e4b0d30dbc8b1c9d /src/Sema.zig | |
| parent | c9c3ee704c45efe0e19bd02c08f51c7513268e76 (diff) | |
| download | zig-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.zig | 21 |
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); |
