-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
6 changed files
with
105 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
const S = struct { x: u32 = 0 }; | ||
const T = struct { []const u8 }; | ||
|
||
fn test0() !void { | ||
const x: u8 = try 1; | ||
_ = x; | ||
} | ||
|
||
fn test1() !void { | ||
const x: S = try .{}; | ||
_ = x; | ||
} | ||
|
||
fn test2() !void { | ||
const x: S = try .{ .x = 123 }; | ||
_ = x; | ||
} | ||
|
||
fn test3() !void { | ||
const x: S = try try .{ .x = 123 }; | ||
_ = x; | ||
} | ||
|
||
fn test4() !void { | ||
const x: T = try .{"hello"}; | ||
_ = x; | ||
} | ||
|
||
fn test5() !void { | ||
const x: error{Foo}!u32 = 123; | ||
_ = try try x; | ||
} | ||
|
||
comptime { | ||
_ = &test0; | ||
_ = &test1; | ||
_ = &test2; | ||
_ = &test3; | ||
_ = &test4; | ||
_ = &test5; | ||
} | ||
|
||
// error | ||
// | ||
// :5:23: error: expected error union type, found 'comptime_int' | ||
// :10:23: error: expected error union type, found '@TypeOf(.{})' | ||
// :15:23: error: expected error union type, found 'tmp.test2__struct_493' | ||
// :15:23: note: struct declared here | ||
// :20:27: error: expected error union type, found 'tmp.test3__struct_495' | ||
// :20:27: note: struct declared here | ||
// :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }' | ||
// :31:13: error: expected error union type, found 'u32' |