Files
scriptc/tests/diagnostics/contract-nothrow-handlers.ts
T
Malte Ubl ad2fcfbc27 try/catch discharges NoThrow: handlers take what they catch
The may-throw analysis now models handlers. A throwing operation or call
inside a `try` with a `catch`, or inside a try/catch whose `finally`
never completes normally (it returns, breaks or continues, discarding the
pending exception), adds no seed and no call edge. The catch and finally
bodies are analyzed like any other code, so rethrows and a finally that
re-raises stay exact. Worker programs (a termination request unwinds
through catch) and generator bodies (a `.return()` does too) keep the
conservative answer.

Unreachable statements no longer seed: the frontend's SC9002 trap after a
body that returns from both its try and its catch (or ends in a switch
with a default, or an infinite loop) is dead code. On tsc-ts this drops
14 functions from the may-throw set and 44 pending-exception checks.

A NoThrow function may now contain handled calls; the SC7001 hint names
the remedy that applies (catch it, remove the recursion, or the worker
exception).
2026-10-11 16:30:24 -07:00

41 lines
951 B
TypeScript

// try/catch discharges NoThrow only for the exceptions its handlers take: a
// finally that can complete normally re-raises, and a rethrow in a catch
// propagates. `handled` holds its contract.
import type { NoThrow } from "@scriptc/types";
class Counter {
count = 0;
}
function parseDigit(ch: number): number {
if (ch < 48 || ch > 57) throw new RangeError("not a digit");
return ch - 48;
}
function cleanup(text: string, counter: Counter): NoThrow<number> {
try {
return parseDigit(text.charCodeAt(0));
} finally {
counter.count++;
}
}
function rethrows(text: string): NoThrow<number> {
try {
return parseDigit(text.charCodeAt(0));
} catch (error) {
if (text.length > 1) throw error;
return -1;
}
}
function handled(text: string): NoThrow<number> {
try {
return parseDigit(text.charCodeAt(0));
} catch {
return -1;
}
}
console.log(cleanup("1", new Counter()), rethrows("2"), handled("x"));