authorgravatar for will.lillis24@gmail.comWill Lillis <will.lillis24@gmail.com> 2025-01-26 13:38:07-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-01-26 19:38:07+01:00
log672bc8141fd26b29eb645571be27420db8e4c27e
tree2f6879b2a1bb3190493a09de66f14f479fff8237
parent9c6d728b0c9350b0661c8da1134d4fd623b88713
signaturebadge-check Signed by PGP key B5690EEEBB952194

fix: Only suggest try on destructure of error union if payload type can be destructured (#21510)


2 files changed, 25 insertions(+), 8 deletions(-)

src/Sema.zig+12-8
...@@ -5525,6 +5525,14 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -5525,6 +5525,14 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
5525 }5525 }
5526}5526}
55275527
5528fn typeIsDestructurable(ty: Type, zcu: *const Zcu) bool {
5529 return switch (ty.zigTypeTag(zcu)) {
5530 .array, .vector => true,
5531 .@"struct" => ty.isTuple(zcu),
5532 else => false,
5533 };
5534}
5535
5528fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {5536fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
5529 const pt = sema.pt;5537 const pt = sema.pt;
5530 const zcu = pt.zcu;5538 const zcu = pt.zcu;
...@@ -5535,19 +5543,15 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -5535,19 +5543,15 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
5535 const operand = try sema.resolveInst(extra.operand);5543 const operand = try sema.resolveInst(extra.operand);
5536 const operand_ty = sema.typeOf(operand);5544 const operand_ty = sema.typeOf(operand);
55375545
5538 const can_destructure = switch (operand_ty.zigTypeTag(zcu)) {5546 if (!typeIsDestructurable(operand_ty, zcu)) {
5539 .array, .vector => true,
5540 .@"struct" => operand_ty.isTuple(zcu),
5541 else => false,
5542 };
5543
5544 if (!can_destructure) {
5545 return sema.failWithOwnedErrorMsg(block, msg: {5547 return sema.failWithOwnedErrorMsg(block, msg: {
5546 const msg = try sema.errMsg(src, "type '{}' cannot be destructured", .{operand_ty.fmt(pt)});5548 const msg = try sema.errMsg(src, "type '{}' cannot be destructured", .{operand_ty.fmt(pt)});
5547 errdefer msg.destroy(sema.gpa);5549 errdefer msg.destroy(sema.gpa);
5548 try sema.errNote(destructure_src, msg, "result destructured here", .{});5550 try sema.errNote(destructure_src, msg, "result destructured here", .{});
5549 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {5551 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {
5550 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});5552 const base_op_ty = operand_ty.errorUnionPayload(zcu);
5553 if (typeIsDestructurable(base_op_ty, zcu))
5554 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
5551 }5555 }
5552 break :msg msg;5556 break :msg msg;
5553 });5557 });
test/cases/compile_errors/invalid_destructure_error_union.zig created+13
...@@ -0,0 +1,13 @@
1pub export fn entry() void {
2 const foo: anyerror!u32 = error.Failure;
3 const bar, const baz = foo;
4 _ = bar;
5 _ = baz;
6}
7
8// error
9// backend=stage2
10// target=native
11//
12// :3:28: error: type 'anyerror!u32' cannot be destructured
13// :3:26: note: result destructured here