Skip to content

R-1a: an equation's value is never a promise (MISSING_AWAIT) - #19

Merged
ryansolid merged 1 commit into
mainfrom
claude/project-thread-89qd4k
Oct 29, 2026
Merged

ryansolid merged 1 commit into
mainfrom
claude/project-thread-89qd4k

Conversation

@ryansolid

Copy link
Copy Markdown
Owner

Requested by Ryan · project thread

Why

R-1 said "a Promise-valued expression without await is an ordinary value of type Promise and is never pending." The compiled app does something else. x = fetchUser(id) lowers to a memo, and Solid's memo consumes a promise its function returns. Checked on the pinned next (ac28157a): createMemo(() => promise) read by an effect gives 42, not a Promise. So the spec, the interpreter and the checker treated x as a value, while the compiled app treated it as pending.

What

  • spec/04 R-1a (new, ruled 2026-10-28). An equation's value is never a promise or an async iterable. Where the type is known, an equation that may be one on any branch is MISSING_AWAIT. A promise inside a value ({ p }, [a, b]) is not consumed. Where the type is any, the check is silent and Solid still consumes the promise. Refusing an any-typed JS import call without await is noted as possible future work, not adopted.
  • spec/13 TY-5b. Equations are projected as __.eq(e, true). The new prelude eq<T> refuses a promise or a stream, following the same pattern as WIRE_VALUE (TY-5a). There is no run-time cost.
  • Diagnostics. MISSING_AWAIT rows added to the 04 table and to 99.
  • ref/ and the crate, kept in step. ref/types/project.ts, ref/types/run.ts (reports MISSING_AWAIT by name), compiler/src/project.rs and compiler/src/prelude.ts.
  • S-types-1. Two new type-check variants: a bare promise, and a promise on one branch of ?:.

await stays the marker for where async enters the graph (R-1, AC-1b/c/d, ASYNC_WATERFALL). This change only makes the missing marker an error instead of silently doing something different.

Checked

  • npm run types: 146 pass, 0 fail. No existing scenario or example equation held a promise.
  • RX_CRATE=1 npm run types: 146 pass, 0 fail.
  • npm run crate: 307/307 programs agree. npm run crate -- --project: 178/178 projections are identical, and all position mappings hold.
  • npm test: all scenarios pass. cargo test: passes.

Generated by Claude Code

An equation lowers to a memo, and Solid's memo consumes a promise or async
iterable its function returns, so R-1's "a Promise-valued expression without
await is an ordinary value" contradicted the lowering. The type projection now
wraps each equation as __.eq(e), which refuses a promise or a stream on any
branch as MISSING_AWAIT (13 TY-5b). `any` stays silent; noted in R-1a.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117BoWMgQnVJdZuGmj1hSdC
@ryansolid ryansolid self-assigned this Oct 28, 2026
@ryansolid
ryansolid merged commit b787012 into main Oct 29, 2026
14 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.

2 participants