aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMitchell Hashimoto <mitchell.hashimoto@gmail.com>2022-03-02 19:01:55 -0800
committerGitHub <noreply@github.com>2022-03-02 22:01:55 -0500
commitac7028f559d888f61f19589c1ead1f6cdeace736 (patch)
treebf88fc6513bbc2943c2c36abd25fd3ea36424951 /src
parentf5e2e301e98fe93f63b5b997e03fa73ed1798a26 (diff)
downloadzig-ac7028f559d888f61f19589c1ead1f6cdeace736.tar.gz
zig-ac7028f559d888f61f19589c1ead1f6cdeace736.zip
stage2: implement @errSetCast (#11039)
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig41
-rw-r--r--src/value.zig19
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;