-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Supply result type to operand of try
#19777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Speaking as a bit of a layman to the compiler jargon, might I ask what type of code this would allow which currently is not allowed? |
@InKryption the usecase I was initially considering when suggesting this was #9938. With decl literals and this both implemented, you'd be able to do stuff like Other usecases are a bit more niche, but one example is |
A slightly less esoteric use-case today is |
Proposal seems fine, let's see if the implementation turns up any complications. Related: |
There is a really esoteric annoying case, which you'd need something like this to repro: const my_slice: []const u32 = &try (if (foo) error.Bar else .{@intCast(bar)}); We can't forward slice ref result locations through This is ridiculously esoteric. We could solve it in the future by changing how we represent ref result locations in the compiler, but for now I'm just making this drop the result type. If someone actually hits this in the wild, I will visit a clothing store and ingest every available hat. |
This is mainly useful in conjunction with Decl Literals (ziglang#9938). Resolves: ziglang#19777
This is mainly useful in conjunction with Decl Literals (ziglang#9938). Resolves: ziglang#19777
This commit effectively reverts 9e683f0, and hence un-accepts ziglang#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: ziglang#21991 Resolves: ziglang#22633
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
Short lil proposal today!
In general, syntax forms which "extract" components of an operand cannot provide result types to said operands. For instance, a field access
x.foo
clearly cannot provide a result type to the expressionx
, as there may be arbitrarily many aggregate types with a field namedfoo
. In general, the same is true of error handling: for instance,x catch ...
cannot provide a result type tox
even if the overall expression has a result type, because while this type may contain sufficient information to determine the payload type, we cannot determine the error type.However, there is one interesting exception here! The
try
operator could, in theory, provide a correct result type to its operand. If an expressiontry x
has result typeT
, then the sub-expressionx
can be assigned result typeE!T
, whereE
is the error set of the current function. Because the behavior oftry
is more limited than that of e.g.catch
, we may not know the error set type that the expression will actually return, but we do know that it must be coercible to the error set of this function, and we lose no information from applying this rule (the result would have been coerced to this type by theret_node
ZIR in the error path regardless). This coercion will correctly handle growing an IES, both runtime and ad-hoc. The more I think about it, the more this seems to me like a no-brainer.Many thanks to @silversquirl for suggesting this to me :D
The text was updated successfully, but these errors were encountered: