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

This commit is contained in:
Will Lillis 2025-01-26 13:38:07 -05:00 committed by GitHub
parent 9c6d728b0c
commit 672bc8141f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 8 deletions

View File

@ -5525,6 +5525,14 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
} }
} }
fn typeIsDestructurable(ty: Type, zcu: *const Zcu) bool {
return switch (ty.zigTypeTag(zcu)) {
.array, .vector => true,
.@"struct" => ty.isTuple(zcu),
else => false,
};
}
fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
const pt = sema.pt; const pt = sema.pt;
const zcu = pt.zcu; const zcu = pt.zcu;
@ -5535,19 +5543,15 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
const operand = try sema.resolveInst(extra.operand); const operand = try sema.resolveInst(extra.operand);
const operand_ty = sema.typeOf(operand); const operand_ty = sema.typeOf(operand);
const can_destructure = switch (operand_ty.zigTypeTag(zcu)) { if (!typeIsDestructurable(operand_ty, zcu)) {
.array, .vector => true,
.@"struct" => operand_ty.isTuple(zcu),
else => false,
};
if (!can_destructure) {
return sema.failWithOwnedErrorMsg(block, msg: { return sema.failWithOwnedErrorMsg(block, msg: {
const msg = try sema.errMsg(src, "type '{}' cannot be destructured", .{operand_ty.fmt(pt)}); const msg = try sema.errMsg(src, "type '{}' cannot be destructured", .{operand_ty.fmt(pt)});
errdefer msg.destroy(sema.gpa); errdefer msg.destroy(sema.gpa);
try sema.errNote(destructure_src, msg, "result destructured here", .{}); try sema.errNote(destructure_src, msg, "result destructured here", .{});
if (operand_ty.zigTypeTag(pt.zcu) == .error_union) { if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {
try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); const base_op_ty = operand_ty.errorUnionPayload(zcu);
if (typeIsDestructurable(base_op_ty, zcu))
try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
} }
break :msg msg; break :msg msg;
}); });

View File

@ -0,0 +1,13 @@
pub export fn entry() void {
const foo: anyerror!u32 = error.Failure;
const bar, const baz = foo;
_ = bar;
_ = baz;
}
// error
// backend=stage2
// target=native
//
// :3:28: error: type 'anyerror!u32' cannot be destructured
// :3:26: note: result destructured here