import type { ScopeInfo, TypeCheckerContext } from "./types.js"; import type { InterruptEffect } from "../symbolTable.js"; import type { ObjectType } from "../types/typeHints.js"; /** * TYPE-ONLY pass (runs after the interrupt effect analysis, BEFORE `buildFlowGraphs` * / `checkScopes`): re-declare each eligible inline handler param as * `handlerParamType(kinds, registry)` — a per-effect discriminated union carrying * each effect's declared payload as `data`. Does NOT touch handler * registration/execution — it only calls `info.scope.declare`. * * Eligibility: inline handler, no explicit `with (e: T)` annotation, non-empty * known raisable-effect set, and no nested `handle` in the body. Otherwise the * param stays `any` (already declared by buildScopes) → conservative. * * SOUNDNESS — colliding param names. `Scope.declare` writes to the FUNCTION scope * and overwrites, so an inline handler param clobbers ANY same-named inline * handler param in the same function scope (including one with an explicit * annotation or one skipped for a nested handle). We count EVERY inline handler * param name in the scope and skip any name used more than once → those stay as * declared by buildScopes (a missed warning, never a wrong one). * * SOUNDNESS — nested handles. `collectRaisableEffects` walks the whole body, * including inside a nested `handle`, so it counts effects the inner handler * already catches → over-reporting → a false "missing case". Handlers whose body * contains a nested handle are not eligible (fall back to `any`). * * Runs each scope under `ctx.withScope(info.scopeKey, …)` so `collectRaisableEffects` * → `synthType` resolves scope-local type aliases against the right scope (mirrors * as the retired AG3010 check did). */ export declare function refineInlineHandlerParams(scopes: ScopeInfo[], interruptEffectsByFunction: Record, ctx: TypeCheckerContext, registry: Record): void;