aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Sengir <william@sengir.com>2022-05-11 03:36:58 -0700
committerWilliam Sengir <william@sengir.com>2022-05-11 03:47:03 -0700
commit363cdb7d5fc376dfb6fc0f67d983922fc4208aa1 (patch)
treecb404d97b91469fabb0b975ee8b423cadacc0572
parentbd32a0f3db2d03749e7aef22cbc2aa6f85b689d1 (diff)
downloadzig-363cdb7d5fc376dfb6fc0f67d983922fc4208aa1.tar.gz
zig-363cdb7d5fc376dfb6fc0f67d983922fc4208aa1.zip
Sema: add error for disjoint error sets in `zirErrSetCast`
-rw-r--r--src/Sema.zig41
1 files changed, 39 insertions, 2 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index d12b85e097..5f584fe40c 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -14209,9 +14209,46 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
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(block, src, dest_ty);
+ // operand must be defined since it can be an invalid error value
+ const maybe_operand_val = try sema.resolveDefinedValue(block, operand_src, operand);
+
+ if (disjoint: {
+ // Try avoiding resolving inferred error sets if we can
+ if (!dest_ty.isAnyError() and dest_ty.errorSetNames().len == 0) break :disjoint true;
+ if (!operand_ty.isAnyError() and operand_ty.errorSetNames().len == 0) break :disjoint true;
+ if (dest_ty.isAnyError()) break :disjoint false;
+ if (operand_ty.isAnyError()) break :disjoint false;
+ for (dest_ty.errorSetNames()) |dest_err_name|
+ if (operand_ty.errorSetHasField(dest_err_name))
+ break :disjoint false;
+
+ if (dest_ty.tag() != .error_set_inferred and operand_ty.tag() != .error_set_inferred)
+ break :disjoint true;
+
+ try sema.resolveInferredErrorSetTy(block, dest_ty_src, dest_ty);
+ try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty);
+ for (dest_ty.errorSetNames()) |dest_err_name|
+ if (operand_ty.errorSetHasField(dest_err_name))
+ break :disjoint false;
+
+ break :disjoint true;
+ }) {
+ const msg = msg: {
+ const msg = try sema.errMsg(
+ block,
+ src,
+ "error sets '{}' and '{}' have no common errors",
+ .{ operand_ty.fmt(sema.mod), dest_ty.fmt(sema.mod) },
+ );
+ errdefer msg.destroy(sema.gpa);
+ try sema.addDeclaredHereNote(msg, operand_ty);
+ try sema.addDeclaredHereNote(msg, dest_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(block, msg);
+ }
+ if (maybe_operand_val) |val| {
if (!dest_ty.isAnyError()) {
const error_name = val.castTag(.@"error").?.data.name;
if (!dest_ty.errorSetHasField(error_name)) {