diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-02-01 08:07:14 +0000 |
|---|---|---|
| committer | Matthew Lugg <mlugg@mlugg.co.uk> | 2025-02-01 15:48:45 +0000 |
| commit | 3924f173af51c50ac18be2166fe115555241778e (patch) | |
| tree | ee3fa65cc85dd6022af6533068dc3fb4f46461ab /src | |
| parent | c225b780e3944014300555c3b45eaccd7bc7c8ae (diff) | |
| download | zig-3924f173af51c50ac18be2166fe115555241778e.tar.gz zig-3924f173af51c50ac18be2166fe115555241778e.zip | |
compiler: do not propagate result type to `try` operand
This commit effectively reverts 9e683f0, and hence un-accepts #19777.
While nice in theory, this proposal turned out to have a few problems.
Firstly, supplying a result type implicitly coerces the operand to this
type -- that's the main point of result types! But for `try`, this is
actually a bad idea; we want a redundant `try` to be a compile error,
not to silently coerce the non-error value to an error union. In
practice, this didn't always happen, because the implementation was
buggy anyway; but when it did, it was really quite silly. For instance,
`try try ... try .{ ... }` was an accepted expression, with the inner
initializer being initially coerced to `E!E!...E!T`.
Secondly, the result type inference here didn't play nicely with
`return`. If you write `return try`, the operand would actually receive
a result type of `E!E!T`, since the `return` gave a result type of `E!T`
and the `try` wrapped it in *another* error union. More generally, the
problem here is that `try` doesn't know when it should or shouldn't
nest error unions. This occasionally broke code which looked like it
should work.
So, this commit prevents `try` from propagating result types through to
its operand. A key motivation for the original proposal here was decl
literals; so, as a special case, `try .foo(...)` is still an allowed
syntax form, caught by AstGen and specially lowered. This does open the
doors to allowing other special cases for decl literals in future, such
as `.foo(...) catch ...`, but those proposals are for another time.
Resolves: #21991
Resolves: #22633
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 16 | ||||
| -rw-r--r-- | src/print_zir.zig | 2 |
2 files changed, 0 insertions, 18 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 93b367b9d8..5c1b6a10f5 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1257,8 +1257,6 @@ fn analyzeBodyInner( .validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst), .opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst), .coerce_ptr_elem_ty => try sema.zirCoercePtrElemTy(block, inst), - .try_operand_ty => try sema.zirTryOperandTy(block, inst, false), - .try_ref_operand_ty => try sema.zirTryOperandTy(block, inst, true), .clz => try sema.zirBitCount(block, inst, .clz, Value.clz), .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz), @@ -2085,20 +2083,6 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; cur = un_node.operand; }, - .try_operand_ty => { - // Either the input type was itself poison, or it was a slice, which we cannot translate - // to an overall result type. - const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_ref = try sema.resolveInst(un_node.operand); - if (operand_ref == .generic_poison_type) { - // The input was poison -- keep looking. - cur = un_node.operand; - continue; - } - // We got a poison because the result type was a slice. This is a tricky case -- let's just - // not bother explaining it to the user for now... - return .unknown; - }, .struct_init_field_type => { const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.FieldType, pl_node.payload_index).data; diff --git a/src/print_zir.zig b/src/print_zir.zig index afa94f40ed..d04ef46c9f 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -278,8 +278,6 @@ const Writer = struct { .opt_eu_base_ptr_init, .restore_err_ret_index_unconditional, .restore_err_ret_index_fn_entry, - .try_operand_ty, - .try_ref_operand_ty, => try self.writeUnNode(stream, inst), .ref, |
