diff --git a/CHANGELOG.md b/CHANGELOG.md index 25b275dda6..28e1b4a987 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - Fix issue with overlapping labelled argument with default value https://github.com/rescript-lang/syntax/pull/734 - Fix issue with using alias and default value together https://github.com/rescript-lang/syntax/pull/734 - Fix issue in `Js.Promise2` where `then` and `catch` were returning `undefined` https://github.com/rescript-lang/rescript-compiler/pull/5996 +- Fix issue in the compiler back-end where async functions passed to an `@uncurry` external would be inlined and transformed in a way that loses async https://github.com/rescript-lang/rescript-compiler/pull/6011 #### :rocket: New Feature diff --git a/jscomp/core/lam_eta_conversion.ml b/jscomp/core/lam_eta_conversion.ml index 91f9534f76..25f5bd1957 100644 --- a/jscomp/core/lam_eta_conversion.ml +++ b/jscomp/core/lam_eta_conversion.ml @@ -113,13 +113,16 @@ let unsafe_adjust_to_arity loc ~(to_ : int) ?(from : int option) (fn : Lam.t) : let ap_info : Lam.ap_info = { ap_loc = loc; ap_inlined = Default_inline; ap_status = App_na } in + let is_async_fn = match fn with + | Lfunction { attr = {async}} -> async + | _ -> false in match (from, fn) with | Some from, _ | None, Lfunction { arity = from } -> ( - if from = to_ then fn + if from = to_ || is_async_fn then fn else if to_ = 0 then match fn with - | Lfunction { params = [ param ]; body; attr = {async} } -> - Lam.function_ ~arity:0 ~attr:{Lambda.default_function_attribute with async} + | Lfunction { params = [ param ]; body } -> + Lam.function_ ~arity:0 ~attr:Lambda.default_function_attribute ~params:[] ~body:(Lam.let_ Alias param Lam.unit body) (* could be only introduced by diff --git a/jscomp/test/async_inline.js b/jscomp/test/async_inline.js index be36ca2a3a..ce18be4f26 100644 --- a/jscomp/test/async_inline.js +++ b/jscomp/test/async_inline.js @@ -1,6 +1,7 @@ 'use strict'; var Curry = require("../../lib/js/curry.js"); +var React = require("react"); async function willBeInlined(param) { return 3; @@ -50,6 +51,12 @@ async function nested2(param) { }; } +function onSubmit(param) { + return React.useCallback(async function (_a, b) { + return await b; + }); +} + exports.willBeInlined = willBeInlined; exports.inlined = inlined; exports.wrapSomethingAsync = wrapSomethingAsync; @@ -58,4 +65,5 @@ exports.M = M; exports.broken = broken$2; exports.nested1 = nested1; exports.nested2 = nested2; +exports.onSubmit = onSubmit; /* inlined Not a pure module */ diff --git a/jscomp/test/async_inline.res b/jscomp/test/async_inline.res index ede76f1821..9bf823cabc 100644 --- a/jscomp/test/async_inline.res +++ b/jscomp/test/async_inline.res @@ -39,4 +39,14 @@ let broken = someAsyncFunction => broken(someAsyncFunction) let nested1 = () => async (y) => await y -let nested2 = async () => async (y) => await y \ No newline at end of file +let nested2 = async () => async (y) => await y + +type callback<'input, 'output> = 'input => 'output + +@module("react") +external useCallback: (@uncurry ('input => 'output)) => callback<'input, 'output> = "useCallback" + +let onSubmit = () => + useCallback(async (_a, b) => { + await b + }) diff --git a/lib/4.06.1/unstable/js_compiler.ml b/lib/4.06.1/unstable/js_compiler.ml index 49275be74e..a0b1123752 100644 --- a/lib/4.06.1/unstable/js_compiler.ml +++ b/lib/4.06.1/unstable/js_compiler.ml @@ -98870,13 +98870,16 @@ let unsafe_adjust_to_arity loc ~(to_ : int) ?(from : int option) (fn : Lam.t) : let ap_info : Lam.ap_info = { ap_loc = loc; ap_inlined = Default_inline; ap_status = App_na } in + let is_async_fn = match fn with + | Lfunction { attr = {async}} -> async + | _ -> false in match (from, fn) with | Some from, _ | None, Lfunction { arity = from } -> ( - if from = to_ then fn + if from = to_ || is_async_fn then fn else if to_ = 0 then match fn with - | Lfunction { params = [ param ]; body; attr = {async} } -> - Lam.function_ ~arity:0 ~attr:{Lambda.default_function_attribute with async} + | Lfunction { params = [ param ]; body } -> + Lam.function_ ~arity:0 ~attr:Lambda.default_function_attribute ~params:[] ~body:(Lam.let_ Alias param Lam.unit body) (* could be only introduced by diff --git a/lib/4.06.1/unstable/js_playground_compiler.ml b/lib/4.06.1/unstable/js_playground_compiler.ml index adee0870ad..bcc024fd71 100644 --- a/lib/4.06.1/unstable/js_playground_compiler.ml +++ b/lib/4.06.1/unstable/js_playground_compiler.ml @@ -98870,13 +98870,16 @@ let unsafe_adjust_to_arity loc ~(to_ : int) ?(from : int option) (fn : Lam.t) : let ap_info : Lam.ap_info = { ap_loc = loc; ap_inlined = Default_inline; ap_status = App_na } in + let is_async_fn = match fn with + | Lfunction { attr = {async}} -> async + | _ -> false in match (from, fn) with | Some from, _ | None, Lfunction { arity = from } -> ( - if from = to_ then fn + if from = to_ || is_async_fn then fn else if to_ = 0 then match fn with - | Lfunction { params = [ param ]; body; attr = {async} } -> - Lam.function_ ~arity:0 ~attr:{Lambda.default_function_attribute with async} + | Lfunction { params = [ param ]; body } -> + Lam.function_ ~arity:0 ~attr:Lambda.default_function_attribute ~params:[] ~body:(Lam.let_ Alias param Lam.unit body) (* could be only introduced by diff --git a/lib/4.06.1/whole_compiler.ml b/lib/4.06.1/whole_compiler.ml index 22c9bde26b..e3864ac9ff 100644 --- a/lib/4.06.1/whole_compiler.ml +++ b/lib/4.06.1/whole_compiler.ml @@ -268166,13 +268166,16 @@ let unsafe_adjust_to_arity loc ~(to_ : int) ?(from : int option) (fn : Lam.t) : let ap_info : Lam.ap_info = { ap_loc = loc; ap_inlined = Default_inline; ap_status = App_na } in + let is_async_fn = match fn with + | Lfunction { attr = {async}} -> async + | _ -> false in match (from, fn) with | Some from, _ | None, Lfunction { arity = from } -> ( - if from = to_ then fn + if from = to_ || is_async_fn then fn else if to_ = 0 then match fn with - | Lfunction { params = [ param ]; body; attr = {async} } -> - Lam.function_ ~arity:0 ~attr:{Lambda.default_function_attribute with async} + | Lfunction { params = [ param ]; body } -> + Lam.function_ ~arity:0 ~attr:Lambda.default_function_attribute ~params:[] ~body:(Lam.let_ Alias param Lam.unit body) (* could be only introduced by