Repository navigation
Reject await in a function that an async function returns directly - #9169
Conversation
Why:
The built-in PPX let a function in the body of an async function
inherit its async context, so `await` in a plain arrow returned by an
async function passed the check, and the JavaScript had `await` in a
function that is not async (#9168). The inheritance comes from the
curried parsetree, where `async (x, y) => ...` was nested functions;
in the n-ary parsetree a function in a function's body is a function
of its own, so each function is now in an async context exactly when
it is async.
Diagnostic added (await in a returned function):
Example:
let f = async x => y => await y + x
Before (js): a SyntaxError when the module loads
async function f(x) {
return y => await y + x | 0;
}
After (diagnostic):
A.res:1:25-31
Await on expression not in an async context
Review: Does a working program stop compiling? Only one whose `await` in
such a function was removed by the optimizer, as in an unused
definition or a branch under a constant `false`; the same code in any
other plain function is already rejected. Programs that still compile
give the same JavaScript, since only the await check reads the async
context.
Signed-off-by: mununki <woonki.moon@gmail.com>
Changelog🐛 Bug fix
Semantic Diff1 commit · Full page Reject await in a function that an async function returns directly1cb2b80 · mununki · Nov 01, 2026, 18:02 UTC
Diagnostic added (await in a returned function) let f = async x => y => await y + x
async function f(x) {
return y => await y + x | 0;
}
Review
|
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #9169 +/- ##
==========================================
- Coverage 81.67% 81.67% -0.01%
==========================================
Files 455 455
Lines 64859 64857 -2
==========================================
- Hits 52974 52972 -2
Misses 11885 11885
🚀 New features to boost your workflow:
|
rescript
@rescript/belt
@rescript/darwin-arm64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/runtime
@rescript/win32-x64
commit: |
|
Developer playground preview: https://rescript-lang.github.io/rescript/dev-playground/?version=pr-9169 |
Fixes: #9168
awaitin a plain arrow that an async function returns directly passed the await check, solet f = async x => y => await y + xcompiled toasync function f(x) { return y => await y + x | 0; }, which fails to load with a SyntaxError.The built-in PPX gave a function in the body of a function the async context of its parent (
async_context := (old_in_function_def && !async_context) || asyncinbs_builtin_ppx.ml). That was needed whenasync (x, y) => ...was nestedPexp_funnodes. #8566 kept it, but in the n-ary parsetree aPexp_funholds all parameters of its function, so aPexp_funin its body is always a function of its own. A function is now in an async context exactly when it is async, andin_function_def, which served only this, is removed.awaitin a function that is not async, except where the optimizer had removed theawait(an unused definition, a branch under a constantfalse). The same code in any other plain function is already rejected.async (x, y) => await y,async x => async y => await y,awaitin the async function's own parameter defaults, and@directiveon async functions with several parameters (Fix @directive on function level with async and multiple parameters #7977).Tests: a super_errors fixture for the rejected case, and mocha tests for async functions that return async and plain functions.
Checklist
changes/README.md), or no release notes are needed and a maintainer should applychangelog:skip.CONTRIBUTING.md).git commit -s).