Reject await in a functor body
Why
The built-in PPX checks await against an async context that each Pexp_fun sets to whether its function is async. A functor is a Pmod_functor module expression, which left the context as it was, so its body took the context around it: true at the top level of a file, where await is allowed, and in an async function. A functor compiles to a JavaScript function that is not async, so the output had await in a plain function. A functor body is now not an async context, and the context around the functor is restored after it. In a structure, module M = await List was not checked at all, so it passed in a functor body or a module nested in a plain function; it is now checked as in an expression.
addedDiagnostic await in a functor body
module type S = { let p: promise<int>}module F = (X: S) => { let v = await X.p}
js
function F(X) { let v = await X.p; return { v: v };}
diagnostic
A.res:5:11-19Await on expression not in an async context
addedDiagnostic dynamic import in a module in a plain function
let f = values => { module M = { module L = await List let n = L.length(values) } M.n}
js
function f(values) { let L = await import("@rescript/runtime/lib/es6/Stdlib_List.mjs"); let n = L.length(values); return n;}
diagnostic
A.res:3:16-25Await on expression not in an async context
addedDiagnostic functor applied where it is defined
module type S = { let p: promise<int>}let f = async p => { module F = (X: S) => { let v = await X.p } module M = F({ let p = p }) M.v}
js
async function f(p) { let v = await p; return v;}
diagnostic
A.res:6:13-21Await on expression not in an async context
Review
- Does a working program stop compiling? Yes, where the optimizer inlined every application of the functor and dropped the functor: a functor defined and applied in an async function, as above, a top-level functor that an interface or a signature hides, and a functor applied where it is written. That depends on the optimization: after
module G = F,G({...})is not inlined andFstays a function withawaitin it. Also rejected aremodule M = await (List: {...}), which imports nothing dynamically, in a functor body or a module in a plain function, as in an expression already, andawaitin a functor undermodule type of. Programs that still compile give the same JavaScript.