Commit 9106fdffaf

Veikka Tuominen <git@vexu.eu>
2024-03-28 14:37:48
Sema: check error union payload types in `@errorCast`
1 parent 60614b2
Changed files (2)
src
test
cases
src/Sema.zig
@@ -22636,6 +22636,21 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
     if (dest_tag == .ErrorSet and operand_tag == .ErrorUnion) {
         return sema.fail(block, src, "cannot cast an error union type to error set", .{});
     }
+    if (dest_tag == .ErrorUnion and operand_tag == .ErrorUnion and
+        base_dest_ty.errorUnionPayload(mod).toIntern() != base_operand_ty.errorUnionPayload(mod).toIntern())
+    {
+        return sema.failWithOwnedErrorMsg(block, msg: {
+            const msg = try sema.errMsg(block, src, "payload types of error unions must match", .{});
+            errdefer msg.destroy(sema.gpa);
+            const dest_ty = base_dest_ty.errorUnionPayload(mod);
+            const operand_ty = base_operand_ty.errorUnionPayload(mod);
+            try sema.errNote(block, src, msg, "destination payload is '{}'", .{dest_ty.fmt(mod)});
+            try sema.errNote(block, src, msg, "operand payload is '{}'", .{operand_ty.fmt(mod)});
+            try addDeclaredHereNote(sema, msg, dest_ty);
+            try addDeclaredHereNote(sema, msg, operand_ty);
+            break :msg msg;
+        });
+    }
     const dest_ty = if (dest_tag == .ErrorUnion) base_dest_ty.errorUnionSet(mod) else base_dest_ty;
     const operand_ty = if (operand_tag == .ErrorUnion) base_operand_ty.errorUnionSet(mod) else base_operand_ty;
 
test/cases/compile_errors/@errorCast_with_bad_type.zig
@@ -13,6 +13,11 @@ export fn entry3() void {
     const a: anyerror = @errorCast(e);
     _ = a;
 }
+pub export fn entry4() void {
+    const a: anyerror!u32 = 123;
+    const b: anyerror!f32 = @errorCast(a);
+    _ = b;
+}
 
 // error
 // backend=stage2
@@ -21,3 +26,6 @@ export fn entry3() void {
 // :4:25: error: expected error set or error union type, found 'ComptimeInt'
 // :8:20: error: expected error set or error union type, found 'Int'
 // :13:25: error: cannot cast an error union type to error set
+// :18:29: error: payload types of error unions must match
+// :18:29: note: destination payload is 'f32'
+// :18:29: note: operand payload is 'u32'