stage2: Pop error trace when storing error to var/const
In order to enforce a strict stack discipline for error return traces,
we cannot track error return traces that are stored in variables:
```zig
const x = errorable(); // errorable()'s error return trace is killed here
// v-- error trace starts here instead
return x catch error.UnknownError;
```
In order to propagate error return traces, function calls need to be passed
directly to an error-handling expression (`if`, `catch`, `try` or `return`):
```zig
// When passed directly to `catch`, the return trace is propagated
return errorable() catch error.UnknownError;
// Using a break also works
return blk: {
// code here
break :blk errorable();
} catch error.UnknownError;
```
Why do we need this restriction? Without it, multiple errors can co-exist
with their own error traces. Handling that situation correctly means either:
a. Dynamically allocating trace memory and tracking lifetimes, OR
b. Allowing the production of one error to interfere with the trace of another
(which is the current status quo)
This is piece (3/3) of https://github.com/ziglang/zig/issues/1923#issuecomment-1218495574
This commit is contained in:
@@ -208,6 +208,58 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
},
|
||||
});
|
||||
|
||||
cases.addCase(.{
|
||||
.name = "stored errors do not contribute to error trace",
|
||||
.source =
|
||||
\\fn foo() !void {
|
||||
\\ return error.TheSkyIsFalling;
|
||||
\\}
|
||||
\\
|
||||
\\pub fn main() !void {
|
||||
\\ // Once an error is stored in a variable, it is popped from the trace
|
||||
\\ var x = foo();
|
||||
\\ x = {};
|
||||
\\
|
||||
\\ // As a result, this error trace will still be clean
|
||||
\\ return error.SomethingUnrelatedWentWrong;
|
||||
\\}
|
||||
,
|
||||
.Debug = .{
|
||||
.expect =
|
||||
\\error: SomethingUnrelatedWentWrong
|
||||
\\source.zig:11:5: [address] in main (test)
|
||||
\\ return error.SomethingUnrelatedWentWrong;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
},
|
||||
.ReleaseSafe = .{
|
||||
.exclude_os = .{
|
||||
.windows, // TODO
|
||||
.linux, // defeated by aggressive inlining
|
||||
},
|
||||
.expect =
|
||||
\\error: SomethingUnrelatedWentWrong
|
||||
\\source.zig:11:5: [address] in [function]
|
||||
\\ return error.SomethingUnrelatedWentWrong;
|
||||
\\ ^
|
||||
\\
|
||||
,
|
||||
},
|
||||
.ReleaseFast = .{
|
||||
.expect =
|
||||
\\error: SomethingUnrelatedWentWrong
|
||||
\\
|
||||
,
|
||||
},
|
||||
.ReleaseSmall = .{
|
||||
.expect =
|
||||
\\error: SomethingUnrelatedWentWrong
|
||||
\\
|
||||
,
|
||||
},
|
||||
});
|
||||
|
||||
cases.addCase(.{
|
||||
.name = "try return from within catch",
|
||||
.source =
|
||||
|
||||
Reference in New Issue
Block a user