| author | |
| committer | |
| log | 8e1421f19ef3daea9b8a414bd5783189bc292676 |
| tree | cf642506120e82fed3de9c4a32a2232492d49b94 |
| parent | d8bfbbbf25984cfdc4d50a92569523a0a151d9e6 |
| parent | 0b1ba6eb521a15b38b08f9923dd84329487d5755 |
| signature |
Sema: implement `@errSetCast` for error unions16 files changed, 110 insertions(+), 66 deletions(-)
doc/langref.html.in+6-6| ... | @@ -6657,7 +6657,7 @@ test "coercion from homogenous tuple to array" { | ... | @@ -6657,7 +6657,7 @@ test "coercion from homogenous tuple to array" { |
| 6657 | <li>{#link|@alignCast#} - make a pointer have more alignment</li> | 6657 | <li>{#link|@alignCast#} - make a pointer have more alignment</li> |
| 6658 | <li>{#link|@enumFromInt#} - obtain an enum value based on its integer tag value</li> | 6658 | <li>{#link|@enumFromInt#} - obtain an enum value based on its integer tag value</li> |
| 6659 | <li>{#link|@errorFromInt#} - obtain an error code based on its integer value</li> | 6659 | <li>{#link|@errorFromInt#} - obtain an error code based on its integer value</li> |
| 6660 | <li>{#link|@errSetCast#} - convert to a smaller error set</li> | 6660 | <li>{#link|@errorCast#} - convert to a smaller error set</li> |
| 6661 | <li>{#link|@floatCast#} - convert a larger float to a smaller float</li> | 6661 | <li>{#link|@floatCast#} - convert a larger float to a smaller float</li> |
| 6662 | <li>{#link|@floatFromInt#} - convert an integer to a float value</li> | 6662 | <li>{#link|@floatFromInt#} - convert an integer to a float value</li> |
| 6663 | <li>{#link|@intCast#} - convert between integer types</li> | 6663 | <li>{#link|@intCast#} - convert between integer types</li> |
| ... | @@ -8410,10 +8410,10 @@ test "main" { | ... | @@ -8410,10 +8410,10 @@ test "main" { |
| 8410 | </p> | 8410 | </p> |
| 8411 | {#header_close#} | 8411 | {#header_close#} |
| 8412 | 8412 | ||
| 8413 | {#header_open|@errSetCast#} | 8413 | {#header_open|@errorCast#} |
| 8414 | <pre>{#syntax#}@errSetCast(value: anytype) anytype{#endsyntax#}</pre> | 8414 | <pre>{#syntax#}@errorCast(value: anytype) anytype{#endsyntax#}</pre> |
| 8415 | <p> | 8415 | <p> |
| 8416 | Converts an error value from one error set to another error set. The return type is the | 8416 | Converts an error set or error union value from one error set to another error set. The return type is the |
| 8417 | 			inferred result type. Attempting to convert an error which is not in the destination error | 8417 | 			inferred result type. Attempting to convert an error which is not in the destination error |
| 8418 | 			set results in safety-protected {#link|Undefined Behavior#}. | 8418 | 			set results in safety-protected {#link|Undefined Behavior#}. |
| 8419 | </p> | 8419 | </p> |
| ... | @@ -10257,7 +10257,7 @@ const Set2 = error{ | ... | @@ -10257,7 +10257,7 @@ const Set2 = error{ |
| 10257 | C, | 10257 | C, |
| 10258 | }; | 10258 | }; |
| 10259 | comptime { | 10259 | comptime { |
| 10260 | _ = @as(Set2, @errSetCast(Set1.B)); | 10260 | _ = @as(Set2, @errorCast(Set1.B)); |
| 10261 | } | 10261 | } |
| 10262 | {#code_end#} | 10262 | {#code_end#} |
| 10263 | <p>At runtime:</p> | 10263 | <p>At runtime:</p> |
| ... | @@ -10276,7 +10276,7 @@ pub fn main() void { | ... | @@ -10276,7 +10276,7 @@ pub fn main() void { |
| 10276 | foo(Set1.B); | 10276 | foo(Set1.B); |
| 10277 | } | 10277 | } |
| 10278 | fn foo(set1: Set1) void { | 10278 | fn foo(set1: Set1) void { |
| 10279 | const x: Set2 = @errSetCast(set1); | 10279 | const x: Set2 = @errorCast(set1); |
| 10280 | std.debug.print("value: {}\n", .{x}); | 10280 | std.debug.print("value: {}\n", .{x}); |
| 10281 | } | 10281 | } |
| 10282 | {#code_end#} | 10282 | {#code_end#} |
lib/std/child_process.zig+2-2| ... | @@ -446,7 +446,7 @@ pub const ChildProcess = struct { | ... | @@ -446,7 +446,7 @@ pub const ChildProcess = struct { |
| 446 | // has a value greater than 0 | 446 | // has a value greater than 0 |
| 447 | if ((fd[0].revents & std.os.POLL.IN) != 0) { | 447 | if ((fd[0].revents & std.os.POLL.IN) != 0) { |
| 448 | const err_int = try readIntFd(err_pipe[0]); | 448 | const err_int = try readIntFd(err_pipe[0]); |
| 449 | return @as(SpawnError, @errSetCast(@errorFromInt(err_int))); | 449 | return @as(SpawnError, @errorCast(@errorFromInt(err_int))); |
| 450 | } | 450 | } |
| 451 | } else { | 451 | } else { |
| 452 | // Write maxInt(ErrInt) to the write end of the err_pipe. This is after | 452 | // Write maxInt(ErrInt) to the write end of the err_pipe. This is after |
| ... | @@ -459,7 +459,7 @@ pub const ChildProcess = struct { | ... | @@ -459,7 +459,7 @@ pub const ChildProcess = struct { |
| 459 | // Here we potentially return the fork child's error from the parent | 459 | // Here we potentially return the fork child's error from the parent |
| 460 | // pid. | 460 | // pid. |
| 461 | if (err_int != maxInt(ErrInt)) { | 461 | if (err_int != maxInt(ErrInt)) { |
| 462 | return @as(SpawnError, @errSetCast(@errorFromInt(err_int))); | 462 | return @as(SpawnError, @errorCast(@errorFromInt(err_int))); |
| 463 | } | 463 | } |
| 464 | } | 464 | } |
| 465 | } | 465 | } |
lib/std/os.zig+1-1| ... | @@ -5419,7 +5419,7 @@ pub fn dl_iterate_phdr( | ... | @@ -5419,7 +5419,7 @@ pub fn dl_iterate_phdr( |
| 5419 | } | 5419 | } |
| 5420 | }.callbackC, @as(?*anyopaque, @ptrFromInt(@intFromPtr(&context))))) { | 5420 | }.callbackC, @as(?*anyopaque, @ptrFromInt(@intFromPtr(&context))))) { |
| 5421 | 0 => return, | 5421 | 0 => return, |
| 5422 | else => |err| return @as(Error, @errSetCast(@errorFromInt(@as(u16, @intCast(err))))), // TODO don't hardcode u16 | 5422 | else => |err| return @as(Error, @errorCast(@errorFromInt(@as(u16, @intCast(err))))), // TODO don't hardcode u16 |
| 5423 | } | 5423 | } |
| 5424 | } | 5424 | } |
| 5425 | 5425 |
lib/std/zig/render.zig+3-1| ... | @@ -1444,7 +1444,7 @@ fn renderBuiltinCall( | ... | @@ -1444,7 +1444,7 @@ fn renderBuiltinCall( |
| 1444 | const slice = tree.tokenSlice(builtin_token); | 1444 | const slice = tree.tokenSlice(builtin_token); |
| 1445 | const rewrite_two_param_cast = params.len == 2 and for ([_][]const u8{ | 1445 | const rewrite_two_param_cast = params.len == 2 and for ([_][]const u8{ |
| 1446 | "@bitCast", | 1446 | "@bitCast", |
| 1447 | "@errSetCast", | 1447 | "@errorCast", |
| 1448 | "@floatCast", | 1448 | "@floatCast", |
| 1449 | "@intCast", | 1449 | "@intCast", |
| 1450 | "@ptrCast", | 1450 | "@ptrCast", |
| ... | @@ -1505,6 +1505,8 @@ fn renderBuiltinCall( | ... | @@ -1505,6 +1505,8 @@ fn renderBuiltinCall( |
| 1505 | try ais.writer().writeAll("@intFromPtr"); | 1505 | try ais.writer().writeAll("@intFromPtr"); |
| 1506 | } else if (mem.eql(u8, slice, "@fabs")) { | 1506 | } else if (mem.eql(u8, slice, "@fabs")) { |
| 1507 | try ais.writer().writeAll("@abs"); | 1507 | try ais.writer().writeAll("@abs"); |
| 1508 | } else if (mem.eql(u8, slice, "@errSetCast")) { | ||
| 1509 | try ais.writer().writeAll("@errorCast"); | ||
| 1508 | } else { | 1510 | } else { |
| 1509 | try renderToken(ais, tree, builtin_token, .none); // @name | 1511 | try renderToken(ais, tree, builtin_token, .none); // @name |
| 1510 | } | 1512 | } |
src/AstGen.zig+3-3| ... | @@ -8454,11 +8454,11 @@ fn builtinCall( | ... | @@ -8454,11 +8454,11 @@ fn builtinCall( |
| 8454 | }); | 8454 | }); |
| 8455 | return rvalue(gz, ri, result, node); | 8455 | return rvalue(gz, ri, result, node); |
| 8456 | }, | 8456 | }, |
| 8457 | .err_set_cast => { | 8457 | .error_cast => { |
| 8458 | try emitDbgNode(gz, node); | 8458 | try emitDbgNode(gz, node); |
| 8459 | 8459 | ||
| 8460 | const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{ | 8460 | const result = try gz.addExtendedPayload(.error_cast, Zir.Inst.BinNode{ |
| 8461 | .lhs = try ri.rl.resultTypeForCast(gz, node, "@errSetCast"), | 8461 | .lhs = try ri.rl.resultTypeForCast(gz, node, "@errorCast"), |
| 8462 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]), | 8462 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]), |
| 8463 | .node = gz.nodeIndexToRelative(node), | 8463 | .node = gz.nodeIndexToRelative(node), |
| 8464 | }); | 8464 | }); |
src/AstRlAnnotate.zig+1-1| ... | @@ -945,7 +945,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. | ... | @@ -945,7 +945,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 945 | .float_cast, | 945 | .float_cast, |
| 946 | .int_cast, | 946 | .int_cast, |
| 947 | .truncate, | 947 | .truncate, |
| 948 | .err_set_cast, | 948 | .error_cast, |
| 949 | .ptr_cast, | 949 | .ptr_cast, |
| 950 | .align_cast, | 950 | .align_cast, |
| 951 | .addrspace_cast, | 951 | .addrspace_cast, |
src/BuiltinFn.zig+3-3| ... | @@ -43,7 +43,7 @@ pub const Tag = enum { | ... | @@ -43,7 +43,7 @@ pub const Tag = enum { |
| 43 | error_name, | 43 | error_name, |
| 44 | error_return_trace, | 44 | error_return_trace, |
| 45 | int_from_error, | 45 | int_from_error, |
| 46 | err_set_cast, | 46 | error_cast, |
| 47 | @"export", | 47 | @"export", |
| 48 | @"extern", | 48 | @"extern", |
| 49 | fence, | 49 | fence, |
| ... | @@ -455,9 +455,9 @@ pub const list = list: { | ... | @@ -455,9 +455,9 @@ pub const list = list: { |
| 455 | }, | 455 | }, |
| 456 | }, | 456 | }, |
| 457 | .{ | 457 | .{ |
| 458 | "@errSetCast", | 458 | "@errorCast", |
| 459 | .{ | 459 | .{ |
| 460 | .tag = .err_set_cast, | 460 | .tag = .error_cast, |
| 461 | .eval_to_error = .always, | 461 | .eval_to_error = .always, |
| 462 | .param_count = 1, | 462 | .param_count = 1, |
| 463 | }, | 463 | }, |
src/Sema.zig+47-21| ... | @@ -1252,7 +1252,7 @@ fn analyzeBodyInner( | ... | @@ -1252,7 +1252,7 @@ fn analyzeBodyInner( |
| 1252 | .wasm_memory_size => try sema.zirWasmMemorySize( block, extended), | 1252 | .wasm_memory_size => try sema.zirWasmMemorySize( block, extended), |
| 1253 | .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended), | 1253 | .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended), |
| 1254 | .prefetch => try sema.zirPrefetch( block, extended), | 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 | .await_nosuspend => try sema.zirAwaitNosuspend( block, extended), | 1256 | .await_nosuspend => try sema.zirAwaitNosuspend( block, extended), |
| 1257 | .select => try sema.zirSelect( block, extended), | 1257 | .select => try sema.zirSelect( block, extended), |
| 1258 | .int_from_error => try sema.zirIntFromError( block, extended), | 1258 | .int_from_error => try sema.zirIntFromError( block, extended), |
| ... | @@ -21747,17 +21747,31 @@ fn ptrFromIntVal( | ... | @@ -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 | const mod = sema.mod; | 21751 | const mod = sema.mod; |
| 21752 | const ip = &mod.intern_pool; | 21752 | const ip = &mod.intern_pool; |
| 21753 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 21753 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 21754 | const src = LazySrcLoc.nodeOffset(extra.node); | 21754 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 21755 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 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 | const operand = try sema.resolveInst(extra.rhs); | 21757 | const operand = try sema.resolveInst(extra.rhs); |
| 21758 | const operand_ty = sema.typeOf(operand); | 21758 | const base_operand_ty = sema.typeOf(operand); |
| 21759 | try sema.checkErrorSetType(block, src, dest_ty); | 21759 | const dest_tag = base_dest_ty.zigTypeTag(mod); |
| 21760 | try sema.checkErrorSetType(block, operand_src, operand_ty); | 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 | // operand must be defined since it can be an invalid error value | 21776 | // operand must be defined since it can be an invalid error value |
| 21763 | const maybe_operand_val = try sema.resolveDefinedValue(block, operand_src, operand); | 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,8 +21818,15 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 21804 | } | 21818 | } |
| 21805 | 21819 | ||
| 21806 | if (maybe_operand_val) |val| { | 21820 | if (maybe_operand_val) |val| { |
| 21807 | if (!dest_ty.isAnyError(mod)) { | 21821 | if (!dest_ty.isAnyError(mod)) check: { |
| 21808 | const error_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; | 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 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), error_name)) { | 21830 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), error_name)) { |
| 21810 | const msg = msg: { | 21831 | const msg = msg: { |
| 21811 | const msg = try sema.errMsg( | 21832 | const msg = try sema.errMsg( |
| ... | @@ -21822,16 +21843,29 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -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 | try sema.requireRuntimeBlock(block, src, operand_src); | 21849 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 21829 | if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) { | 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); | 21851 | if (dest_tag == .ErrorUnion) { |
| 21831 | const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst); | 21852 | const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand); |
| 21832 | try sema.addSafetyCheck(block, src, ok, .invalid_error_code); | 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 | fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 21871 | fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| ... | @@ -22916,14 +22950,6 @@ fn checkIntOrVectorAllowComptime( | ... | @@ -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 | const SimdBinOp = struct { | 22953 | const SimdBinOp = struct { |
| 22928 | len: ?usize, | 22954 | len: ?usize, |
| 22929 | /// Coerced to `result_ty`. | 22955 | /// Coerced to `result_ty`. |
src/Zir.zig+2-2| ... | @@ -1997,9 +1997,9 @@ pub const Inst = struct { | ... | @@ -1997,9 +1997,9 @@ pub const Inst = struct { |
| 1997 | /// Implements `@setCold`. | 1997 | /// Implements `@setCold`. |
| 1998 | /// `operand` is payload index to `UnNode`. | 1998 | /// `operand` is payload index to `UnNode`. |
| 1999 | set_cold, | 1999 | set_cold, |
| 2000 | /// Implements the `@errSetCast` builtin. | 2000 | /// Implements the `@errorCast` builtin. |
| 2001 | /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. | 2001 | /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. |
| 2002 | err_set_cast, | 2002 | error_cast, |
| 2003 | /// `operand` is payload index to `UnNode`. | 2003 | /// `operand` is payload index to `UnNode`. |
| 2004 | await_nosuspend, | 2004 | await_nosuspend, |
| 2005 | /// Implements `@breakpoint`. | 2005 | /// Implements `@breakpoint`. |
src/print_zir.zig+1-1| ... | @@ -594,7 +594,7 @@ const Writer = struct { | ... | @@ -594,7 +594,7 @@ const Writer = struct { |
| 594 | 594 | ||
| 595 | .builtin_extern, | 595 | .builtin_extern, |
| 596 | .c_define, | 596 | .c_define, |
| 597 | .err_set_cast, | 597 | .error_cast, |
| 598 | .wasm_memory_grow, | 598 | .wasm_memory_grow, |
| 599 | .prefetch, | 599 | .prefetch, |
| 600 | .c_va_arg, | 600 | .c_va_arg, |
stage1/zig1.wasm| Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ | |||
test/behavior/error.zig+18-2| ... | @@ -228,13 +228,29 @@ const Set1 = error{ A, B }; | ... | @@ -228,13 +228,29 @@ const Set1 = error{ A, B }; |
| 228 | const Set2 = error{ A, C }; | 228 | const Set2 = error{ A, C }; |
| 229 | 229 | ||
| 230 | fn testExplicitErrorSetCast(set1: Set1) !void { | 230 | fn testExplicitErrorSetCast(set1: Set1) !void { |
| 231 | var x = @as(Set2, @errSetCast(set1)); | 231 | var x = @as(Set2, @errorCast(set1)); |
| 232 | try expect(@TypeOf(x) == Set2); | 232 | try expect(@TypeOf(x) == Set2); |
| 233 | var y = @as(Set1, @errSetCast(x)); | 233 | var y = @as(Set1, @errorCast(x)); |
| 234 | try expect(@TypeOf(y) == Set1); | 234 | try expect(@TypeOf(y) == Set1); |
| 235 | try expect(y == error.A); | 235 | try expect(y == error.A); |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | test "@errorCast on error unions" { | ||
| 239 | const S = struct { | ||
| 240 | fn doTheTest() !void { | ||
| 241 | const casted: error{Bad}!i32 = @errorCast(retErrUnion()); | ||
| 242 | try expect((try casted) == 1234); | ||
| 243 | } | ||
| 244 | |||
| 245 | fn retErrUnion() anyerror!i32 { | ||
| 246 | return 1234; | ||
| 247 | } | ||
| 248 | }; | ||
| 249 | |||
| 250 | try S.doTheTest(); | ||
| 251 | try comptime S.doTheTest(); | ||
| 252 | } | ||
| 253 | |||
| 238 | test "comptime test error for empty error set" { | 254 | test "comptime test error for empty error set" { |
| 239 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 255 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 240 | 256 |
test/cases/compile_errors/explicit_error_set_cast_known_at_comptime_violates_error_sets.zig+1-1| ... | @@ -2,7 +2,7 @@ const Set1 = error{ A, B }; | ... | @@ -2,7 +2,7 @@ const Set1 = error{ A, B }; |
| 2 | const Set2 = error{ A, C }; | 2 | const Set2 = error{ A, C }; |
| 3 | comptime { | 3 | comptime { |
| 4 | var x = Set1.B; | 4 | var x = Set1.B; |
| 5 | var y: Set2 = @errSetCast(x); | 5 | var y: Set2 = @errorCast(x); |
| 6 | _ = y; | 6 | _ = y; |
| 7 | } | 7 | } |
| 8 | 8 |
test/cases/compile_errors/int_to_err_non_global_invalid_number.zig+1-1| ... | @@ -8,7 +8,7 @@ const Set2 = error{ | ... | @@ -8,7 +8,7 @@ const Set2 = error{ |
| 8 | }; | 8 | }; |
| 9 | comptime { | 9 | comptime { |
| 10 | var x = @intFromError(Set1.B); | 10 | var x = @intFromError(Set1.B); |
| 11 | var y: Set2 = @errSetCast(@errorFromInt(x)); | 11 | var y: Set2 = @errorCast(@errorFromInt(x)); |
| 12 | _ = y; | 12 | _ = y; |
| 13 | } | 13 | } |
| 14 | 14 |
test/cases/safety/@errSetCast error not present in destination.zig	 deleted-21| ... | @@ -1,21 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "invalid error code")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | const Set1 = error{ A, B }; | ||
| 11 | const Set2 = error{ A, C }; | ||
| 12 | pub fn main() !void { | ||
| 13 | foo(Set1.B) catch {}; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | fn foo(set1: Set1) Set2 { | ||
| 17 | return @errSetCast(set1); | ||
| 18 | } | ||
| 19 | // run | ||
| 20 | // backend=llvm | ||
| 21 | // target=native | ||
test/cases/safety/@errorCast error not present in destination.zig	 created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | ||
| 4 | _ = stack_trace; | ||
| 5 | if (std.mem.eql(u8, message, "invalid error code")) { | ||
| 6 | std.process.exit(0); | ||
| 7 | } | ||
| 8 | std.process.exit(1); | ||
| 9 | } | ||
| 10 | const Set1 = error{ A, B }; | ||
| 11 | const Set2 = error{ A, C }; | ||
| 12 | pub fn main() !void { | ||
| 13 | foo(Set1.B) catch {}; | ||
| 14 | return error.TestFailed; | ||
| 15 | } | ||
| 16 | fn foo(set1: Set1) Set2 { | ||
| 17 | return @errorCast(set1); | ||
| 18 | } | ||
| 19 | // run | ||
| 20 | // backend=llvm | ||
| 21 | // target=native | ||