Local Fault Handlers (LFH) & Structured Typed Exits #82425
Replies: 1 comment 1 reply
-
|
Please read the readme in this repo. Do not open requests or language changes here. Language change requests start as discussions at dotnet/csharplang. |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Local Fault Handlers (LFH) & Structured Typed Exits
Title: Local Fault Handlers (LFH)
Status: Proposal
Target: C# Language Specification / .NET Runtime
Keywords:
leave,on leave,control-flow,pattern-matching,zero-cost-abstractionRelated: Labeled break and continue Statements
1. Abstract
This proposal introduces Local Fault Handlers, a mechanism for strict, typed, and local control flow transfer. It is designed to replace the ambiguity of
breakin nested loops, the unsafety ofgoto, and the performance overhead of Exceptions when used for flow control.The feature introduces the
leaveoperator to interrupt execution and transfer control to a strictly typedon leaveblock defined at the end of the method scope. This block utilizes C# switch expression syntax for pattern matching, ensuring a clean separation of the "Happy Path" from edge cases while guaranteeing type safety and deterministic resource disposal.2. Motivation
Modern imperative programming often struggles with complex control flow in three specific areas:
switchstatement nested within a loop requires boolean flags (bool keepLooping), labelled loops, orgoto. All are verbose or error-prone.ValidationException) incurs significant runtime costs (stack trace generation, unwinding).Result<T>) forces developers to checkif (result.IsFailure) return result;after every operation, obscuring the primary algorithm.LFH solves these issues by treating local exits not as system failures, but as Typed State Transitions. It provides the performance of a jump instruction with the safety of a compiler-checked switch.
3. Detailed Design
3.1. The
leaveOperatorThe
leaveoperator terminates the current block of execution and transfers control to the method'son leavesection. It accepts a payload, which can be a Nominal Type (class/struct) or a Structural Type (ValueTuple).3.2. The
on leaveHandlerThe handler is defined at the end of the method body. It adopts the concise syntax of C# Switch Expressions.
leave.on leavearms execute statements (blocks).returnorthrow). Fall-through or resuming execution of the original block is prohibited.3.3. Semantic Rules & Safety
3.3.1. Scope & Locality
The
leaveoperator works strictly within the bounds of a single method (or lambda/local function). It cannot jump across method boundaries.3.3.2. Strict Exhaustiveness
The compiler performs static analysis to ensure all types emitted by
leaveare handled.leave (int, int), theon leaveblock must contain a pattern matching(int, int).3.3.3. Resource Management (RAII)
The mechanism respects
usingblocks. Whenleaveis invoked, the runtime guarantees thatDispose()is called for allIDisposableobjects in the scopes being exited before the jump to the handler occurs.3.4. Tuple Support (Anonymous States)
To reduce boilerplate (avoiding the need to define a
structfor every local error), LFH supportsValueTuple.4. Examples
Scenario A: Replacing
gotoin Nested LoopsGoal: Exit a nested loop cleanly with context.
Scenario B: Replacing Exceptions for Validation
Goal: Validate input without the performance cost of
try-catch.5. Alternatives Considered
5.1. Block-Scoped Handlers
We considered allowing
on leaveto be attached to any block (e.g.,if (...) { ... } on leave { ... }).try-catchblocks, encourages nesting, and obscures the flow of execution. Restricting handlers to the end of the method enforces a separation of "Logic" vs. "Exit Handling" and encourages smaller methods.5.2. Resumable Handlers
We considered allowing the handler to resume execution after the
leavepoint.leaveis often used when an invariant is broken. Resuming would lead to indeterminate states. Enforcing an exit (return/throw) ensures deterministic behavior.6. Implementation Notes (Compiler Lowering)
The C# compiler (Roslyn) would lower this feature roughly as follows:
on leaveblock is converted into a series of labelled blocks at the end of the method.leave Xis lowered to agoto Label_X.usingstatements are preserved astry-finallyblocks, ensuring thegototriggers thefinally(Dispose) logic.7. Conclusion
Local Fault Handlers elevate "error handling" from a secondary concern to a first-class citizen of the language syntax. By combining the raw speed of
gotowith the safety of type checking and the conciseness of pattern matching, LFH allows C# developers to write code that is:This proposal bridges the gap between low-level systems programming efficiency and high-level application safety.
Beta Was this translation helpful? Give feedback.
All reactions