@@ -1252,7 +1252,7 @@ fn analyzeBodyInner(
1252
1252
.wasm_memory_size => try sema.zirWasmMemorySize( block, extended),
1253
1253
.wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended),
1254
1254
.prefetch => try sema.zirPrefetch( block, extended),
1255
- .err_set_cast => try sema.zirErrSetCast( block, extended),
1255
+ .error_cast => try sema.zirErrorCast( block, extended),
1256
1256
.await_nosuspend => try sema.zirAwaitNosuspend( block, extended),
1257
1257
.select => try sema.zirSelect( block, extended),
1258
1258
.int_from_error => try sema.zirIntFromError( block, extended),
@@ -21747,17 +21747,31 @@ fn ptrFromIntVal(
21747
21747
};
21748
21748
}
21749
21749
21750
- fn zirErrSetCast (sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
21750
+ fn zirErrorCast (sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
21751
21751
const mod = sema.mod;
21752
21752
const ip = &mod.intern_pool;
21753
21753
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
21754
21754
const src = LazySrcLoc.nodeOffset(extra.node);
21755
21755
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
21756
- const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt , "@errSetCast ");
21756
+ const base_dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_opt , "@errorCast ");
21757
21757
const operand = try sema.resolveInst(extra.rhs);
21758
- const operand_ty = sema.typeOf(operand);
21759
- try sema.checkErrorSetType(block, src, dest_ty);
21760
- try sema.checkErrorSetType(block, operand_src, operand_ty);
21758
+ const base_operand_ty = sema.typeOf(operand);
21759
+ const dest_tag = base_dest_ty.zigTypeTag(mod);
21760
+ const operand_tag = base_operand_ty.zigTypeTag(mod);
21761
+ if (dest_tag != operand_tag) {
21762
+ return sema.fail(block, src, "expected source and destination types to match, found '{s}' and '{s}'", .{
21763
+ @tagName(operand_tag), @tagName(dest_tag),
21764
+ });
21765
+ } else if (dest_tag != .ErrorSet and dest_tag != .ErrorUnion) {
21766
+ return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(dest_tag)});
21767
+ }
21768
+ const dest_ty, const operand_ty = if (dest_tag == .ErrorUnion) .{
21769
+ base_dest_ty.errorUnionSet(mod),
21770
+ base_operand_ty.errorUnionSet(mod),
21771
+ } else .{
21772
+ base_dest_ty,
21773
+ base_operand_ty,
21774
+ };
21761
21775
21762
21776
// operand must be defined since it can be an invalid error value
21763
21777
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
21804
21818
}
21805
21819
21806
21820
if (maybe_operand_val) |val| {
21807
- if (!dest_ty.isAnyError(mod)) {
21808
- const error_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
21821
+ if (!dest_ty.isAnyError(mod)) check: {
21822
+ const operand_val = mod.intern_pool.indexToKey(val.toIntern());
21823
+ var error_name: InternPool.NullTerminatedString = undefined;
21824
+ if (dest_tag == .ErrorUnion) {
21825
+ if (operand_val.error_union.val != .err_name) break :check;
21826
+ error_name = operand_val.error_union.val.err_name;
21827
+ } else {
21828
+ error_name = operand_val.err.name;
21829
+ }
21809
21830
if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), error_name)) {
21810
21831
const msg = msg: {
21811
21832
const msg = try sema.errMsg(
@@ -21822,16 +21843,29 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
21822
21843
}
21823
21844
}
21824
21845
21825
- return Air.internedToRef((try mod.getCoerced(val, dest_ty )).toIntern());
21846
+ return Air.internedToRef((try mod.getCoerced(val, base_dest_ty )).toIntern());
21826
21847
}
21827
21848
21828
21849
try sema.requireRuntimeBlock(block, src, operand_src);
21829
21850
if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) {
21830
- const err_int_inst = try block.addBitCast(Type.err_int, operand);
21831
- const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
21832
- try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
21851
+ if (dest_tag == .ErrorUnion) {
21852
+ const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);
21853
+ const err_int = try block.addBitCast(Type.err_int, err_code);
21854
+ const zero_u16 = Air.internedToRef(try mod.intern(.{
21855
+ .int = .{ .ty = .u16_type, .storage = .{ .u64 = 0 } },
21856
+ }));
21857
+
21858
+ const has_value = try block.addTyOp(.error_set_has_value, dest_ty, err_code);
21859
+ const is_zero = try block.addBinOp(.cmp_eq, err_int, zero_u16);
21860
+ const ok = try block.addBinOp(.bit_or, has_value, is_zero);
21861
+ try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
21862
+ } else {
21863
+ const err_int_inst = try block.addBitCast(Type.err_int, operand);
21864
+ const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
21865
+ try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
21866
+ }
21833
21867
}
21834
- return block.addBitCast(dest_ty , operand);
21868
+ return block.addBitCast(base_dest_ty , operand);
21835
21869
}
21836
21870
21837
21871
fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
@@ -22916,14 +22950,6 @@ fn checkIntOrVectorAllowComptime(
22916
22950
}
22917
22951
}
22918
22952
22919
- fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
22920
- const mod = sema.mod;
22921
- switch (ty.zigTypeTag(mod)) {
22922
- .ErrorSet => return,
22923
- else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty.fmt(mod)}),
22924
- }
22925
- }
22926
-
22927
22953
const SimdBinOp = struct {
22928
22954
len: ?usize,
22929
22955
/// Coerced to `result_ty`.
0 commit comments