diff options
| author | Veikka Tuominen <git@vexu.eu> | 2023-10-01 13:16:02 +0300 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2023-10-01 17:00:01 +0300 |
| commit | 63bd2bff12992aef0ce23ae4b344e9cb5d65f05d (patch) | |
| tree | a26b65da14fca381be9266f41f504c332efc3c4b /src | |
| parent | d8bfbbbf25984cfdc4d50a92569523a0a151d9e6 (diff) | |
| download | zig-63bd2bff12992aef0ce23ae4b344e9cb5d65f05d.tar.gz zig-63bd2bff12992aef0ce23ae4b344e9cb5d65f05d.zip | |
Sema: add `@errorCast` which works for both error sets and error unions
Closes #17343
Diffstat (limited to 'src')
| -rw-r--r-- | src/AstGen.zig | 6 | ||||
| -rw-r--r-- | src/AstRlAnnotate.zig | 2 | ||||
| -rw-r--r-- | src/BuiltinFn.zig | 6 | ||||
| -rw-r--r-- | src/Sema.zig | 68 | ||||
| -rw-r--r-- | src/Zir.zig | 4 | ||||
| -rw-r--r-- | src/print_zir.zig | 2 |
6 files changed, 57 insertions, 31 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index 12e33bd803..346177e5ac 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -8454,11 +8454,11 @@ fn builtinCall( }); return rvalue(gz, ri, result, node); }, - .err_set_cast => { + .error_cast => { try emitDbgNode(gz, node); - const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{ - .lhs = try ri.rl.resultTypeForCast(gz, node, "@errSetCast"), + const result = try gz.addExtendedPayload(.error_cast, Zir.Inst.BinNode{ + .lhs = try ri.rl.resultTypeForCast(gz, node, "@errorCast"), .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]), .node = gz.nodeIndexToRelative(node), }); diff --git a/src/AstRlAnnotate.zig b/src/AstRlAnnotate.zig index f9d6804328..c751adea9d 100644 --- a/src/AstRlAnnotate.zig +++ b/src/AstRlAnnotate.zig @@ -945,7 +945,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. .float_cast, .int_cast, .truncate, - .err_set_cast, + .error_cast, .ptr_cast, .align_cast, .addrspace_cast, diff --git a/src/BuiltinFn.zig b/src/BuiltinFn.zig index 0056854e77..3296114ef9 100644 --- a/src/BuiltinFn.zig +++ b/src/BuiltinFn.zig @@ -43,7 +43,7 @@ pub const Tag = enum { error_name, error_return_trace, int_from_error, - err_set_cast, + error_cast, @"export", @"extern", fence, @@ -455,9 +455,9 @@ pub const list = list: { }, }, .{ - "@errSetCast", + "@errorCast", .{ - .tag = .err_set_cast, + .tag = .error_cast, .eval_to_error = .always, .param_count = 1, }, diff --git a/src/Sema.zig b/src/Sema.zig index 963f7f5489..88dd5f5b09 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1252,7 +1252,7 @@ fn analyzeBodyInner( .wasm_memory_size => try sema.zirWasmMemorySize( block, extended), .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended), .prefetch => try sema.zirPrefetch( block, extended), - .err_set_cast => try sema.zirErrSetCast( block, extended), + .error_cast => try sema.zirErrorCast( block, extended), .await_nosuspend => try sema.zirAwaitNosuspend( block, extended), .select => try sema.zirSelect( block, extended), .int_from_error => try sema.zirIntFromError( block, extended), @@ -21747,17 +21747,31 @@ fn ptrFromIntVal( }; } -fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { +fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { const mod = sema.mod; const ip = &mod.intern_pool; const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; const src = LazySrcLoc.nodeOffset(extra.node); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; - const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@errSetCast"); + const base_dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_opt, "@errorCast"); const operand = try sema.resolveInst(extra.rhs); - const operand_ty = sema.typeOf(operand); - try sema.checkErrorSetType(block, src, dest_ty); - try sema.checkErrorSetType(block, operand_src, operand_ty); + const base_operand_ty = sema.typeOf(operand); + const dest_tag = base_dest_ty.zigTypeTag(mod); + const operand_tag = base_operand_ty.zigTypeTag(mod); + if (dest_tag != operand_tag) { + return sema.fail(block, src, "expected source and destination types to match, found '{s}' and '{s}'", .{ + @tagName(operand_tag), @tagName(dest_tag), + }); + } else if (dest_tag != .ErrorSet and dest_tag != .ErrorUnion) { + return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(dest_tag)}); + } + const dest_ty, const operand_ty = if (dest_tag == .ErrorUnion) .{ + base_dest_ty.errorUnionSet(mod), + base_operand_ty.errorUnionSet(mod), + } else .{ + base_dest_ty, + base_operand_ty, + }; // operand must be defined since it can be an invalid error value const maybe_operand_val = try sema.resolveDefinedValue(block, operand_src, operand); @@ -21804,8 +21818,15 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat } if (maybe_operand_val) |val| { - if (!dest_ty.isAnyError(mod)) { - const error_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; + if (!dest_ty.isAnyError(mod)) check: { + const operand_val = mod.intern_pool.indexToKey(val.toIntern()); + var error_name: InternPool.NullTerminatedString = undefined; + if (dest_tag == .ErrorUnion) { + if (operand_val.error_union.val != .err_name) break :check; + error_name = operand_val.error_union.val.err_name; + } else { + error_name = operand_val.err.name; + } if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), error_name)) { const msg = msg: { const msg = try sema.errMsg( @@ -21822,16 +21843,29 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat } } - return Air.internedToRef((try mod.getCoerced(val, dest_ty)).toIntern()); + return Air.internedToRef((try mod.getCoerced(val, base_dest_ty)).toIntern()); } try sema.requireRuntimeBlock(block, src, operand_src); if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) { - 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); - try sema.addSafetyCheck(block, src, ok, .invalid_error_code); + if (dest_tag == .ErrorUnion) { + const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand); + const err_int = try block.addBitCast(Type.err_int, err_code); + const zero_u16 = Air.internedToRef(try mod.intern(.{ + .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); + } 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); + try sema.addSafetyCheck(block, src, ok, .invalid_error_code); + } } - return block.addBitCast(dest_ty, operand); + return block.addBitCast(base_dest_ty, operand); } fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { @@ -22916,14 +22950,6 @@ fn checkIntOrVectorAllowComptime( } } -fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { - const mod = sema.mod; - switch (ty.zigTypeTag(mod)) { - .ErrorSet => return, - else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty.fmt(mod)}), - } -} - const SimdBinOp = struct { len: ?usize, /// Coerced to `result_ty`. diff --git a/src/Zir.zig b/src/Zir.zig index 62c48ecbb6..973177c1b0 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -1997,9 +1997,9 @@ pub const Inst = struct { /// Implements `@setCold`. /// `operand` is payload index to `UnNode`. set_cold, - /// Implements the `@errSetCast` builtin. + /// Implements the `@errorCast` builtin. /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. - err_set_cast, + error_cast, /// `operand` is payload index to `UnNode`. await_nosuspend, /// Implements `@breakpoint`. diff --git a/src/print_zir.zig b/src/print_zir.zig index 5ced6cafe7..d295af2830 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -594,7 +594,7 @@ const Writer = struct { .builtin_extern, .c_define, - .err_set_cast, + .error_cast, .wasm_memory_grow, .prefetch, .c_va_arg, |
