From d060cbbec75ac7b0204c706e4dfdfb38f1b24dfd Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Sun, 25 Sep 2022 19:51:38 -0700 Subject: stage2: Keep error return traces alive when storing to `const` This change extends the "lifetime" of the error return trace associated with an error to continue throughout the block of a `const` variable that it is assigned to. This is necessary to support patterns like this one in test_runner.zig: ```zig const result = foo(); if (result) |_| { // ... success logic } else |err| { // `foo()` should be included in the error trace here return error.TestFailed; } ``` To make this happen, the majority of the error return trace popping logic needed to move into Sema, since `const x = foo();` cannot be examined syntactically to determine whether it modifies the error return trace. We also have to make sure not to delete pertinent block information before it makes it to Sema, so that Sema can pop/restore around blocks correctly. * Why do this only for `const` and not `var`? * There is room to relax things for `var`, but only a little bit. We could do the same thing we do for const and keep the error trace alive for the remainder of the block where the *assignment* happens. Any wider scope would violate the stack discipline for traces, so it's not viable. In the end, I decided the most consistent behavior for the user is just to kill all error return traces assigned to a mutable `var`. --- test/behavior/error.zig | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'test/behavior/error.zig') diff --git a/test/behavior/error.zig b/test/behavior/error.zig index c93d7aebf7..6b64a0dc01 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -830,3 +830,16 @@ test "compare error union and error set" { try expect(a != b); try expect(b != a); } + +fn non_errorable() void { + // Make sure catch works even in a function that does not call any errorable functions. + // + // This test is needed because stage 2's fix for #1923 means that catch blocks interact + // with the error return trace index. + var x: error{Foo}!void = {}; + return x catch {}; +} + +test "catch within a function that calls no errorable functions" { + non_errorable(); +} -- cgit v1.2.3