| author | |
| committer | |
| log | ac7028f559d888f61f19589c1ead1f6cdeace736 |
| tree | bf88fc6513bbc2943c2c36abd25fd3ea36424951 |
| parent | f5e2e301e98fe93f63b5b997e03fa73ed1798a26 |
| signature |
3 files changed, 64 insertions(+), 4 deletions(-)
src/Sema.zig+40-1| ... | ... | @@ -12465,7 +12465,39 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12465 | 12465 | fn zirErrSetCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 12466 | 12466 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 12467 | 12467 | const src = inst_data.src(); |
| 12468 | return sema.fail(block, src, "TODO: Sema.zirErrSetCast", .{}); | |
| 12468 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | |
| 12469 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | |
| 12470 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | |
| 12471 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | |
| 12472 | const operand = sema.resolveInst(extra.rhs); | |
| 12473 | const operand_ty = sema.typeOf(operand); | |
| 12474 | try sema.checkErrorSetType(block, dest_ty_src, dest_ty); | |
| 12475 | try sema.checkErrorSetType(block, operand_src, operand_ty); | |
| 12476 | ||
| 12477 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { | |
| 12478 | try sema.resolveInferredErrorSetTy(dest_ty); | |
| 12479 | ||
| 12480 | if (!dest_ty.isAnyError()) { | |
| 12481 | const error_name = val.castTag(.@"error").?.data.name; | |
| 12482 | if (!dest_ty.errorSetHasField(error_name)) { | |
| 12483 | return sema.fail( | |
| 12484 | block, | |
| 12485 | src, | |
| 12486 | "error.{s} not a member of error set '{}'", | |
| 12487 | .{ error_name, dest_ty }, | |
| 12488 | ); | |
| 12489 | } | |
| 12490 | } | |
| 12491 | ||
| 12492 | return sema.addConstant(dest_ty, val); | |
| 12493 | } | |
| 12494 | ||
| 12495 | try sema.requireRuntimeBlock(block, src); | |
| 12496 | if (block.wantSafety()) { | |
| 12497 | // TODO | |
| 12498 | } | |
| 12499 | ||
| 12500 | return block.addBitCast(dest_ty, operand); | |
| 12469 | 12501 | } |
| 12470 | 12502 | |
| 12471 | 12503 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -12983,6 +13015,13 @@ fn checkIntOrVector( |
| 12983 | 13015 | } |
| 12984 | 13016 | } |
| 12985 | 13017 | |
| 13018 | fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { | |
| 13019 | switch (ty.zigTypeTag()) { | |
| 13020 | .ErrorSet => return, | |
| 13021 | else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty}), | |
| 13022 | } | |
| 13023 | } | |
| 13024 | ||
| 12986 | 13025 | const SimdBinOp = struct { |
| 12987 | 13026 | len: ?usize, |
| 12988 | 13027 | /// Coerced to `result_ty`. |
src/value.zig+17-2| ... | ... | @@ -2067,10 +2067,25 @@ pub const Value = extern union { |
| 2067 | 2067 | } |
| 2068 | 2068 | }, |
| 2069 | 2069 | .ErrorUnion => { |
| 2070 | @panic("TODO implement hashing error union values"); | |
| 2070 | if (val.tag() == .@"error") { | |
| 2071 | std.hash.autoHash(hasher, false); // error | |
| 2072 | const sub_ty = ty.errorUnionSet(); | |
| 2073 | val.hash(sub_ty, hasher); | |
| 2074 | return; | |
| 2075 | } | |
| 2076 | ||
| 2077 | if (val.castTag(.eu_payload)) |payload| { | |
| 2078 | std.hash.autoHash(hasher, true); // payload | |
| 2079 | const sub_ty = ty.errorUnionPayload(); | |
| 2080 | payload.data.hash(sub_ty, hasher); | |
| 2081 | return; | |
| 2082 | } else unreachable; | |
| 2071 | 2083 | }, |
| 2072 | 2084 | .ErrorSet => { |
| 2073 | @panic("TODO implement hashing error set values"); | |
| 2085 | // just hash the literal error value. this is the most stable | |
| 2086 | // thing between compiler invocations. we can't use the error | |
| 2087 | // int cause (1) its not stable and (2) we don't have access to mod. | |
| 2088 | hasher.update(val.getError().?); | |
| 2074 | 2089 | }, |
| 2075 | 2090 | .Enum => { |
| 2076 | 2091 | var enum_space: Payload.U64 = undefined; |
test/behavior/error.zig+7-1| ... | ... | @@ -209,7 +209,11 @@ fn testErrorSetType() !void { |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | 211 | test "explicit error set cast" { |
| 212 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 212 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 213 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 214 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 215 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 216 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 213 | 217 | |
| 214 | 218 | try testExplicitErrorSetCast(Set1.A); |
| 215 | 219 | comptime try testExplicitErrorSetCast(Set1.A); |
| ... | ... | @@ -220,7 +224,9 @@ const Set2 = error{ A, C }; |
| 220 | 224 | |
| 221 | 225 | fn testExplicitErrorSetCast(set1: Set1) !void { |
| 222 | 226 | var x = @errSetCast(Set2, set1); |
| 227 | try expect(@TypeOf(x) == Set2); | |
| 223 | 228 | var y = @errSetCast(Set1, x); |
| 229 | try expect(@TypeOf(y) == Set1); | |
| 224 | 230 | try expect(y == error.A); |
| 225 | 231 | } |
| 226 | 232 |