Skip to content

feat: THR003 — throws {} on callback parameters (?bs 0.9)#81

Merged
marcelofarias merged 1 commit into
mainfrom
botkowski/thr003-callback-throws
May 22, 2026
Merged

feat: THR003 — throws {} on callback parameters (?bs 0.9)#81
marcelofarias merged 1 commit into
mainfrom
botkowski/thr003-callback-throws

Conversation

@marcelofarias
Copy link
Copy Markdown
Owner

Summary

  • Adds THR003: from ?bs 0.9, fires when a function-typed parameter declares throws { X } but the containing fn does not declare throws { X } in its own header.
  • Closes the last leg of the callback-effect-leak trilogy: EFF002 (uses {}), EFF003/EFF004 (reads {}/writes {}), now THR003 (throws {}).
  • throws {} annotations on callback parameter types are stripped from emitted TypeScript (no runtime impact).

Closes #73.

How it works

In parse-fn.ts, buildArgsTs already strips uses {}, reads {}, and writes {} from function-typed parameters and collects them into paramCaps/paramReads/paramWrites. This PR extends that same pattern to throws {}, adding paramThrows to FnDecl.

In eff-check.ts, the THR003 check mirrors EFF003/EFF004: if decl.paramThrows contains labels not present in decl.throws, emit THR003. Gated on ?bs 0.9.

Test plan

  • pnpm -r build && pnpm test — 596/596 pass (9 new tests)
  • Callback declares throws { NetworkError }, outer fn declares nothing → THR003
  • Callback throws is a strict superset of outer fn throws → THR003 (missing types named)
  • Multiple callback params each declaring throws → THR003
  • Outer fn declares exact callback throws → clean
  • Outer fn over-declares throws → clean
  • Callback has no throws {} annotation → clean
  • Below ?bs 0.9 → no THR003
  • throws {} stripped from emitted TypeScript
  • bs explain THR003 returns rule/idiom/rewrite
  • MCP known-codes test updated

🤖 Generated with Claude Code

Closes the "callback throws-leak" vector. If a function-typed parameter
declares `throws { X }`, calling it can surface X — so the outer fn's
throws header must cover it. Mirrors EFF003/EFF004 for reads/writes.

Changes:
- parse-fn.ts: collect paramThrows from buildArgsTs (same stripping
  pattern as paramReads/paramWrites); throws {} stripped from emitted TS
- eff-check.ts: THR003 check — fires at ?bs 0.9 when paramThrows ⊄ decl.throws
- error-codes.ts: THR003 registry entry (rule/idiom/rewrite/example)
- explanations.ts: THR003 long-form MCP explanation
- server.test.ts: THR003 added to KNOWN_CODES assertion
- thr003-check.test.ts: 9 new tests (fires, suppressed, emitted TS)
- CHANGELOG.md: ?bs 0.9 entry

Closes #73.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new compiler diagnostic THR003 (gated on ?bs 0.9) to prevent “callback throws” leakage: if a function-typed parameter declares throws { X }, the containing function must declare throws { X } (or a superset) in its own header. This extends the existing callback-surface checks (EFF003/EFF004) to exception surfaces and ensures throws {} on callback parameter types is stripped from emitted TypeScript.

Changes:

  • Extend fn parsing to collect throws {} labels from function-typed parameters (paramThrows) while stripping them from emitted TS types.
  • Add THR003 enforcement to passEffCheck (mirroring EFF003/EFF004) and register THR003 in error code registries + MCP explanations.
  • Add focused compiler tests for THR003 and update MCP known-codes coverage.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
CHANGELOG.md Documents THR003 behavior and TS-stripping in the ?bs 0.9 “Added” section.
packages/compiler/src/parser/parse-fn.ts Collects callback-parameter throws {} into paramThrows and strips it from emitted TS argument types.
packages/compiler/src/passes/eff-check.ts Implements THR003 check under the existing ?bs 0.9 gate alongside EFF003/EFF004.
packages/compiler/src/error-codes.ts Registers THR003 metadata (rule/idiom/rewrite/example) for bs explain / diagnostics enrichment.
packages/compiler/tests/thr003-check.test.ts Adds coverage for THR003 triggering/suppression, version gating, TS stripping, and diagnostic shape.
packages/mcp/src/explanations.ts Adds MCP explanation content for THR003 (body + fails/passes examples).
packages/mcp/tests/server.test.ts Updates MCP known-codes list to include THR003.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@marcelofarias marcelofarias merged commit 1198937 into main May 22, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RFC: THR003 — under-declared throws from callback parameter throws annotations

2 participants