stage2: Do not pop error trace if result is an error

This allows for errors to be "re-thrown" by yielding any error as the
result of a catch block. For example:

```zig
fn errorable() !void {
    return error.FallingOutOfPlane;
}

fn foo(have_parachute: bool) !void {
    return errorable() catch |err| b: {
        if (have_parachute) {
            // error trace will include the call to errorable()
            break :b error.NoParachute;
        } else {
            return;
        }
    };
}

pub fn main() !void {
    // Anything that returns a non-error does not pollute the error trace.
    try foo(true);

    // This error trace will still include errorable(), whose error was "re-thrown" by foo()
    try foo(false);
}
```

This is piece (2/3) of https://github.com/ziglang/zig/issues/1923#issuecomment-1218495574
This commit is contained in:
Cody Tapscott
2022-09-12 23:09:14 -07:00
parent eda3eb1561
commit 0c3a50fe1c
2 changed files with 200 additions and 89 deletions

View File

@@ -155,6 +155,59 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
},
});
cases.addCase(.{
.name = "catch and re-throw error",
.source =
\\fn foo() !void {
\\ return error.TheSkyIsFalling;
\\}
\\
\\pub fn main() !void {
\\ return foo() catch error.AndMyCarIsOutOfGas;
\\}
,
.Debug = .{
.expect =
\\error: AndMyCarIsOutOfGas
\\source.zig:2:5: [address] in foo (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:6:5: [address] in main (test)
\\ return foo() catch error.AndMyCarIsOutOfGas;
\\ ^
\\
,
},
.ReleaseSafe = .{
.exclude_os = .{
.windows, // TODO
.linux, // defeated by aggressive inlining
},
.expect =
\\error: AndMyCarIsOutOfGas
\\source.zig:2:5: [address] in [function]
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:6:5: [address] in [function]
\\ return foo() catch error.AndMyCarIsOutOfGas;
\\ ^
\\
,
},
.ReleaseFast = .{
.expect =
\\error: AndMyCarIsOutOfGas
\\
,
},
.ReleaseSmall = .{
.expect =
\\error: AndMyCarIsOutOfGas
\\
,
},
});
cases.addCase(.{
.name = "try return from within catch",
.source =