From e31a0c752463a41300bafe7f7731809936679d0d Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sun, 19 Feb 2023 11:18:38 +0100 Subject: [PATCH] Fix: Inline auto curried async functions produce invalid javascript Fixes https://github.com/rescript-lang/rescript-compiler/issues/6007 --- CHANGELOG.md | 1 + jscomp/core/lam_eta_conversion.ml | 9 ++++++--- jscomp/test/async_inline.js | 8 ++++++++ jscomp/test/async_inline.res | 10 ++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 137167e25c..90530e9e86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ These are only breaking changes for unformatted code. - GenType: fix issue with V3 compatibility mode (see https://github.com/rescript-lang/rescript-compiler/issues/5990) https://github.com/rescript-lang/rescript-compiler/pull/5991 - Fix issue in `Js.Promise2` where `then` and `catch` were returning `undefined` https://github.com/rescript-lang/rescript-compiler/pull/5997 - Fix formatting of props spread for multiline JSX expression https://github.com/rescript-lang/rescript-compiler/pull/6006 +- 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/6010 #### :nail_care: Polish 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 cab7ac7dd2..201e7b2f13 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; @@ -72,6 +73,12 @@ async function nested2(param) { }; } +function onSubmit(param) { + return React.useCallback(async function (_a, b) { + return await b; + }); +} + var tci = 3; exports.willBeInlined = willBeInlined; @@ -90,4 +97,5 @@ exports.tui = tui; exports.tuia = tuia; 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 db3de0b4d0..5e3d48d2a4 100644 --- a/jscomp/test/async_inline.res +++ b/jscomp/test/async_inline.res @@ -50,3 +50,13 @@ let tuia = uncurriedIdAsync(. 3) let nested1 = () => async (y) => await y 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 + })