Contextual catch
v0.33.5 added contextual Result catch without turning catch into a
hard keyword.
result_expr catch (err) { handler_expr }
Value flow
For Result<T>:
| Input | Output |
|---|---|
| success | unwrap and yield the success value T; handler is skipped |
| error | bind err:int32, evaluate handler, yield handler result |
The handler expression must also yield T.
func:bad = int32() {
fail 7i32;
};
func:main = int32() {
int32:x = bad() catch (err) { err + 30i32 };
exit x; // 37
};
The binding is scoped
The error name exists only inside the handler body.
int32:x = bad() catch (code) { code + 1i32 };
The binding type is int32, matching the currently shipped .error /
fail lowering path. Earlier design sketches mentioned tbb8; v0.33.5
documented the implementation reality instead of pretending otherwise.
catch is still an identifier
This is valid:
func:main = int32() {
int32:catch = 7i32;
exit catch;
};
Only the exact postfix shape result_expr catch (err) { handler } is
special. C-style try { ... } catch { ... } is still rejected.
Using ? inside a handler
The handler is just an expression. Other Result handlers keep their normal meaning inside it.
int32:x = bad() catch (err) { also_bad() ? (err + 30i32) };
Here the inner ? fallback can refer to the catch binding.
Not exceptions
catch is Result deconstruction/fallback sugar. It does not unwind the
stack, catch thrown exceptions, or change pass / fail control flow.