From 672bc8141fd26b29eb645571be27420db8e4c27e Mon Sep 17 00:00:00 2001 From: Will Lillis Date: Sun, 26 Jan 2025 13:38:07 -0500 Subject: [PATCH] fix: Only suggest try on destructure of error union if payload type can be destructured (#21510) --- src/Sema.zig | 20 +++++++++++-------- .../invalid_destructure_error_union.zig | 13 ++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 test/cases/compile_errors/invalid_destructure_error_union.zig diff --git a/src/Sema.zig b/src/Sema.zig index 6ad12d1382..72b05d078d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -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 { const pt = sema.pt; 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_ty = sema.typeOf(operand); - const can_destructure = switch (operand_ty.zigTypeTag(zcu)) { - .array, .vector => true, - .@"struct" => operand_ty.isTuple(zcu), - else => false, - }; - - if (!can_destructure) { + if (!typeIsDestructurable(operand_ty, zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "type '{}' cannot be destructured", .{operand_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); try sema.errNote(destructure_src, msg, "result destructured here", .{}); 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; }); diff --git a/test/cases/compile_errors/invalid_destructure_error_union.zig b/test/cases/compile_errors/invalid_destructure_error_union.zig new file mode 100644 index 0000000000..48e0c3a2d5 --- /dev/null +++ b/test/cases/compile_errors/invalid_destructure_error_union.zig @@ -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