Skip to content

compiler: do not propagate result type to try operand #22707

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

Merged
merged 1 commit into from
Feb 1, 2025

Conversation

mlugg
Copy link
Member

@mlugg mlugg commented Feb 1, 2025

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


This is a breaking change, but it only breaks a feature implemented after 0.13.0, so doesn't need the "release notes" tag.

Also, closes #21319; that enhancement doesn't make sense after this change.

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
@mlugg mlugg added the breaking Implementing this issue could cause existing code to no longer compile or have different behavior. label Feb 1, 2025
@xdBronch
Copy link
Contributor

xdBronch commented Feb 1, 2025

closes #21319 by just removing the concept :p

@mlugg mlugg merged commit 3924f17 into ziglang:master Feb 1, 2025
10 checks passed
@mlugg mlugg deleted the no-try-res-ty branch May 18, 2025 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior.
Projects
None yet
2 participants