feat: THR003 — throws {} on callback parameters (?bs 0.9)#81
Merged
Conversation
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>
There was a problem hiding this comment.
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.
Closed
10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
?bs 0.9, fires when a function-typed parameter declaresthrows { X }but the containing fn does not declarethrows { X }in its own header.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,buildArgsTsalready stripsuses {},reads {}, andwrites {}from function-typed parameters and collects them intoparamCaps/paramReads/paramWrites. This PR extends that same pattern tothrows {}, addingparamThrowstoFnDecl.In
eff-check.ts, the THR003 check mirrors EFF003/EFF004: ifdecl.paramThrowscontains labels not present indecl.throws, emit THR003. Gated on?bs 0.9.Test plan
pnpm -r build && pnpm test— 596/596 pass (9 new tests)throws { NetworkError }, outer fn declares nothing → THR003throws {}annotation → clean?bs 0.9→ no THR003throws {}stripped from emitted TypeScriptbs explain THR003returns rule/idiom/rewrite🤖 Generated with Claude Code