Skip to content

fix: Nested fn declarations not inferred as async with Promise.await#971

Merged
milkyskies merged 4 commits intomainfrom
fix/bare-await-async-inference
Apr 3, 2026
Merged

fix: Nested fn declarations not inferred as async with Promise.await#971
milkyskies merged 4 commits intomainfrom
fix/bare-await-async-inference

Conversation

@milkyskies
Copy link
Copy Markdown
Collaborator

Summary

  • Nested fn declarations (e.g. handleDragEnd inside a React component) were never marked async by mark_async_functions, which only checked top-level functions and arrows. This caused generated TypeScript to have await inside a non-async function.
  • Bare |> await shorthand (sugar for |> Promise.await) was also not detected by any of the four async-detection functions, causing the same issue even at the top level.

Changes

  • checker.rs: Extended mark_async_functions walker to also process ItemKind::Function inside Block/Collect expressions. Added Identifier("await") detection to body_has_promise_await.
  • checker/items.rs: Added bare await detection to is_promise_await_member.
  • codegen/expr.rs: Added bare await detection to expr_contains_await.
  • interop/tsgo/probe_gen.rs: Added bare await detection to is_promise_await_member.
  • codegen/tests.rs: Added 4 regression tests covering both bugs.

Test plan

  • cargo test — all tests pass including new regression tests
  • cargo fmt — no formatting issues

🤖 Generated with Claude Code

milkyskies and others added 2 commits April 3, 2026 15:01
Four async-detection functions only recognized the qualified
`Promise.await` member pattern, missing the bare `Identifier("await")`
shorthand. This caused the generated TypeScript to contain `await`
inside a non-async function.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mark_async_functions only checked top-level fn declarations and arrows.
Nested fn declarations (e.g. handleDragEnd inside a React component)
were never marked async, causing generated TS to have await in a
non-async function.

Also detect bare `|> await` shorthand in all four async-detection sites.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions bot added the fix label Apr 3, 2026
milkyskies and others added 2 commits April 3, 2026 15:18
expr_contains_await was missing Match recursion and Block const values,
so match arm IIFEs weren't wrapped as async when the body contained
Promise.await. This caused `await` to appear inside non-async IIFEs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Error E041 when a function uses `|> await` but return type is not
  `Promise<T>`, paralleling how `?` requires `Result<T, E>`
- Unannotated async functions now infer `Promise<T>` return type
  (affects hover display and call-site type checking)
- Updated docs to use bare `|> await` shorthand and document the
  return type requirement

closes #972

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@milkyskies milkyskies merged commit 266de21 into main Apr 3, 2026
3 checks passed
@milkyskies milkyskies deleted the fix/bare-await-async-inference branch April 3, 2026 06:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant