From db07632f8ad7b0452a85bd0d4dc7a1cd41153a9c Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sun, 5 Feb 2023 20:36:07 +0100 Subject: [PATCH] Fix issue with async and locally abstract types To fix the printer, the async internal representation via an attribute needs to be preserved on functions starting with a locally abstract type. For this reason, annotations cannot be placed individually on the first locally abstract type, if that's how the function starts. Fixes https://github.com/rescript-lang/rescript-compiler/issues/5974 --- CHANGELOG.md | 1 + jscomp/frontend/bs_builtin_ppx.ml | 5 +++++ res_syntax/src/res_parsetree_viewer.ml | 2 +- res_syntax/tests/printer/expr/asyncAwait.res | 4 ++++ .../printer/expr/expected/asyncAwait.res.txt | 4 ++++ .../printer/expr/expected/newtype.res.txt | 18 ++++++------------ 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 969d8ffd9c..66c8e9193e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ These are only breaking changes for unformatted code. - Fix issue where uncurried functions were incorrectly converting the type of a prop given as a default value to curried https://github.com/rescript-lang/rescript-compiler/pull/5971 - Fix issue with error messages for uncurried functions where expected and given type were swapped https://github.com/rescript-lang/rescript-compiler/pull/5973 - Fix issue with nested async functions, where the inner function would be emitted without `async` https://github.com/rescript-lang/rescript-compiler/pull/5983 +- Fix issue with async context check, and printer, for async functions with locally abstract type https://github.com/rescript-lang/rescript-compiler/pull/5982 #### :nail_care: Polish diff --git a/jscomp/frontend/bs_builtin_ppx.ml b/jscomp/frontend/bs_builtin_ppx.ml index 771562c711..17a23758e8 100644 --- a/jscomp/frontend/bs_builtin_ppx.ml +++ b/jscomp/frontend/bs_builtin_ppx.ml @@ -127,6 +127,11 @@ let expr_mapper ~async_context ~in_function_def (self : mapper) (* Treat @this (. x, y, z) => ... just like @this (x, y, z) => ... *) let fun_expr = Ast_uncurried.exprExtractUncurriedFun e in self.expr self fun_expr + | Pexp_newtype (s, body) -> + let async = Ast_attributes.has_async_payload e.pexp_attributes <> None in + let body = Ast_async.add_async_attribute ~async body in + let res = self.expr self body in + {e with pexp_desc = Pexp_newtype(s, res)} | Pexp_fun (label, _, pat, body) -> ( let async = Ast_attributes.has_async_payload e.pexp_attributes <> None in match Ast_attributes.process_attributes_rev e.pexp_attributes with diff --git a/res_syntax/src/res_parsetree_viewer.ml b/res_syntax/src/res_parsetree_viewer.ml index 603235f812..6004316c28 100644 --- a/res_syntax/src/res_parsetree_viewer.ml +++ b/res_syntax/src/res_parsetree_viewer.ml @@ -182,7 +182,7 @@ let funExpr expr = | expr -> (uncurried, attrsBefore, List.rev acc, expr) in match expr with - | {pexp_desc = Pexp_fun _} -> + | {pexp_desc = Pexp_fun _ | Pexp_newtype _} -> collect ~uncurried:false ~nFun:0 expr.pexp_attributes [] {expr with pexp_attributes = []} | _ when Ast_uncurried.exprIsUncurriedFun expr -> diff --git a/res_syntax/tests/printer/expr/asyncAwait.res b/res_syntax/tests/printer/expr/asyncAwait.res index b8063228d7..5d64207e13 100644 --- a/res_syntax/tests/printer/expr/asyncAwait.res +++ b/res_syntax/tests/printer/expr/asyncAwait.res @@ -120,3 +120,7 @@ let c3 = (. x) => @foo y => x+y type t1 = (. int) => string => bool type t2 = (. int, string) => bool + +let f = async (type a, ()) => { + await Js.Promise.resolve(()) +} \ No newline at end of file diff --git a/res_syntax/tests/printer/expr/expected/asyncAwait.res.txt b/res_syntax/tests/printer/expr/expected/asyncAwait.res.txt index 68417533d1..1b2968683c 100644 --- a/res_syntax/tests/printer/expr/expected/asyncAwait.res.txt +++ b/res_syntax/tests/printer/expr/expected/asyncAwait.res.txt @@ -142,3 +142,7 @@ let c3 = (. x) => {@foo y => x + y} type t1 = (. int) => string => bool type t2 = (. int, string) => bool + +let f = async (type a, ()) => { + await Js.Promise.resolve() +} diff --git a/res_syntax/tests/printer/expr/expected/newtype.res.txt b/res_syntax/tests/printer/expr/expected/newtype.res.txt index 78a7a5549c..39dc430d9b 100644 --- a/res_syntax/tests/printer/expr/expected/newtype.res.txt +++ b/res_syntax/tests/printer/expr/expected/newtype.res.txt @@ -1,19 +1,13 @@ let f = (type t, xs: list) => () -let f = (@attr type t, xs: list) => () +let f = @attr (type t, xs: list) => () let f = (type t, xs: list, type s, ys: list) => () -let f = (@attr type t, xs: list, @attr2 type s, ys: list) => () +let f = @attr (type t, xs: list, @attr2 type s, ys: list) => () let f = (type t u v, xs: list<(t, u, v)>) => () -let f = (@attr type t u v, xs: list<(t, u, v)>) => () +let f = @attr (type t u v, xs: list<(t, u, v)>) => () let f = (type t u v, xs: list<(t, u, v)>, type s w z, ys: list<(s, w, z)>) => () -let f = (@attr type t u v, xs: list<(t, u, v)>, @attr2 type s w z, ys: list<(s, w, z)>) => () -let f = ( - @attr type t, - @attr type s, - xs: list<(t, s)>, - @attr type u, - @attr type v w, - ys: list<(u, v, w)>, -) => () +let f = @attr (type t u v, xs: list<(t, u, v)>, @attr2 type s w z, ys: list<(s, w, z)>) => () +let f = @attr +(type t, @attr type s, xs: list<(t, s)>, @attr type u, @attr type v w, ys: list<(u, v, w)>) => () let mk_formatting_gen: type a b c d e f. formatting_gen => Parsetree.expression =