diff options
| author | Mitchell Hashimoto <mitchell.hashimoto@gmail.com> | 2022-03-02 19:01:55 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-02 22:01:55 -0500 |
| commit | ac7028f559d888f61f19589c1ead1f6cdeace736 (patch) | |
| tree | bf88fc6513bbc2943c2c36abd25fd3ea36424951 /src | |
| parent | f5e2e301e98fe93f63b5b997e03fa73ed1798a26 (diff) | |
| download | zig-ac7028f559d888f61f19589c1ead1f6cdeace736.tar.gz zig-ac7028f559d888f61f19589c1ead1f6cdeace736.zip | |
stage2: implement @errSetCast (#11039)
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 41 | ||||
| -rw-r--r-- | src/value.zig | 19 |
2 files changed, 57 insertions, 3 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index ec8057ddd2..c669f662ad 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -12465,7 +12465,39 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn zirErrSetCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.fail(block, src, "TODO: Sema.zirErrSetCast", .{}); + const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); + const operand = sema.resolveInst(extra.rhs); + const operand_ty = sema.typeOf(operand); + try sema.checkErrorSetType(block, dest_ty_src, dest_ty); + try sema.checkErrorSetType(block, operand_src, operand_ty); + + if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { + try sema.resolveInferredErrorSetTy(dest_ty); + + if (!dest_ty.isAnyError()) { + const error_name = val.castTag(.@"error").?.data.name; + if (!dest_ty.errorSetHasField(error_name)) { + return sema.fail( + block, + src, + "error.{s} not a member of error set '{}'", + .{ error_name, dest_ty }, + ); + } + } + + return sema.addConstant(dest_ty, val); + } + + try sema.requireRuntimeBlock(block, src); + if (block.wantSafety()) { + // TODO + } + + return block.addBitCast(dest_ty, operand); } fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -12983,6 +13015,13 @@ fn checkIntOrVector( } } +fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { + switch (ty.zigTypeTag()) { + .ErrorSet => return, + else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty}), + } +} + const SimdBinOp = struct { len: ?usize, /// Coerced to `result_ty`. diff --git a/src/value.zig b/src/value.zig index 5db780c99b..d576074ba3 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2067,10 +2067,25 @@ pub const Value = extern union { } }, .ErrorUnion => { - @panic("TODO implement hashing error union values"); + if (val.tag() == .@"error") { + std.hash.autoHash(hasher, false); // error + const sub_ty = ty.errorUnionSet(); + val.hash(sub_ty, hasher); + return; + } + + if (val.castTag(.eu_payload)) |payload| { + std.hash.autoHash(hasher, true); // payload + const sub_ty = ty.errorUnionPayload(); + payload.data.hash(sub_ty, hasher); + return; + } else unreachable; }, .ErrorSet => { - @panic("TODO implement hashing error set values"); + // just hash the literal error value. this is the most stable + // thing between compiler invocations. we can't use the error + // int cause (1) its not stable and (2) we don't have access to mod. + hasher.update(val.getError().?); }, .Enum => { var enum_space: Payload.U64 = undefined; |
