From 7e2ace30eb91dc29095fee395d52f0ec2e93a6a9 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Thu, 30 May 2024 07:50:47 +0200 Subject: [PATCH 1/4] Set version to 11.1.1 --- CHANGELOG.md | 2 ++ jscomp/common/bs_version.ml | 2 +- package-lock.json | 4 ++-- package.json | 2 +- packages/std/package.json | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39ae73628c..31a3810eda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ > - :house: [Internal] > - :nail_care: [Polish] +# 11.1.1 + # 11.1.0 #### :bug: Bug Fix diff --git a/jscomp/common/bs_version.ml b/jscomp/common/bs_version.ml index a7dba66da6..394fb99cc6 100644 --- a/jscomp/common/bs_version.ml +++ b/jscomp/common/bs_version.ml @@ -21,6 +21,6 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) -let version = "11.1.0" +let version = "11.1.1" let header = "// Generated by ReScript, PLEASE EDIT WITH CARE" let package_name = ref "rescript" diff --git a/package-lock.json b/package-lock.json index 0dce2c204d..1451c06859 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rescript", - "version": "11.1.0", + "version": "11.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "rescript", - "version": "11.1.0", + "version": "11.1.1", "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE", "bin": { diff --git a/package.json b/package.json index b7c5ca3c7d..0a18d658cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rescript", - "version": "11.1.0", + "version": "11.1.1", "devDependencies": { "mocha": "10.1.0", "nyc": "15.0.0", diff --git a/packages/std/package.json b/packages/std/package.json index 6d1d5a7ccd..5400eea584 100644 --- a/packages/std/package.json +++ b/packages/std/package.json @@ -1,6 +1,6 @@ { "name": "@rescript/std", - "version": "11.1.0", + "version": "11.1.1", "keywords": [ "rescript", "stdlib", From 57d24801f3ddc199a9755f325b797d23cd35a662 Mon Sep 17 00:00:00 2001 From: Shulhi Sapli Date: Thu, 23 May 2024 22:26:51 +0800 Subject: [PATCH 2/4] Fix formatter eats comments on the first argument of a uncurried function (#6763) Print comments inside uncurried arrow function types correctly. --- jscomp/syntax/src/res_comments_table.ml | 3 +++ .../printer/comments/expected/typexpr.res.txt | 14 ++++++++++++++ jscomp/syntax/tests/printer/comments/typexpr.res | 14 ++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/jscomp/syntax/src/res_comments_table.ml b/jscomp/syntax/src/res_comments_table.ml index d12ace5287..3fd0d5e989 100644 --- a/jscomp/syntax/src/res_comments_table.ml +++ b/jscomp/syntax/src/res_comments_table.ml @@ -1799,6 +1799,9 @@ and walkCoreType typ t comments = attach t.trailing typexpr.ptyp_loc afterTyp | Ptyp_variant (rowFields, _, _) -> walkList (rowFields |> List.map (fun rf -> RowField rf)) t comments + | Ptyp_constr + ({txt = Lident "function$"}, [({ptyp_desc = Ptyp_arrow _} as desc); _]) -> + walkCoreType desc t comments | Ptyp_constr (longident, typexprs) -> let beforeLongident, _afterLongident = partitionLeadingTrailing comments longident.loc diff --git a/jscomp/syntax/tests/printer/comments/expected/typexpr.res.txt b/jscomp/syntax/tests/printer/comments/expected/typexpr.res.txt index b672ab4da0..5741dde63c 100644 --- a/jscomp/syntax/tests/printer/comments/expected/typexpr.res.txt +++ b/jscomp/syntax/tests/printer/comments/expected/typexpr.res.txt @@ -79,3 +79,17 @@ type jsUser = /* before */ { // above age /* before age */ "age" /* after age */: /* before int */ int /* after int */, } /* after */ + +external test: ( + // comment 1 + ~int: int, + // comment 2 + ~int: int, +) => unit = "test" + +external another_test: ( + // comment 1 + int, + // comment 2 + int, +) => unit = "test" diff --git a/jscomp/syntax/tests/printer/comments/typexpr.res b/jscomp/syntax/tests/printer/comments/typexpr.res index 296ad2ff8b..9cb8c16134 100644 --- a/jscomp/syntax/tests/printer/comments/typexpr.res +++ b/jscomp/syntax/tests/printer/comments/typexpr.res @@ -64,3 +64,17 @@ type jsUser = /* before */ { // above age /* before age */"age" /* after age */: /*before int */ int /*after int */ } /* after */ + +external test: ( + // comment 1 + ~int: int, + // comment 2 + ~int: int, +) => unit = "test" + +external another_test: ( + // comment 1 + int, + // comment 2 + int, +) => unit = "test" From 5936649ac5d8e8ffb02f210c24fde101aeb76927 Mon Sep 17 00:00:00 2001 From: Shulhi Sapli Date: Fri, 24 May 2024 20:34:04 +0800 Subject: [PATCH 3/4] Fix parens removed in series of pipes for anonymous uncurried function (#6766) Handle precedence of uncurried anonymous function in pipe chains. # Conflicts: # CHANGELOG.md --- CHANGELOG.md | 5 +++++ jscomp/syntax/src/res_parens.ml | 1 + .../syntax/tests/printer/expr/expected/smartPipe.res.txt | 8 ++++++++ jscomp/syntax/tests/printer/expr/smartPipe.res | 7 +++++++ 4 files changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31a3810eda..b710211946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ # 11.1.1 +#### :bug: Bug Fix + +- Fix formatter eats comments on the first argument of a uncurried function. https://github.com/rescript-lang/rescript-compiler/pull/6763 +- Fix formatter removes parens in pipe operator with anonymous uncurried function. https://github.com/rescript-lang/rescript-compiler/pull/6766 + # 11.1.0 #### :bug: Bug Fix diff --git a/jscomp/syntax/src/res_parens.ml b/jscomp/syntax/src/res_parens.ml index 5fc2ab9ff8..4c699c9a31 100644 --- a/jscomp/syntax/src/res_parens.ml +++ b/jscomp/syntax/src/res_parens.ml @@ -180,6 +180,7 @@ let flattenOperandRhs parentOperator rhs = let precParent = ParsetreeViewer.operatorPrecedence parentOperator in let precChild = ParsetreeViewer.operatorPrecedence operator in precParent >= precChild || rhs.pexp_attributes <> [] + | Pexp_construct ({txt = Lident "Function$"}, Some _) -> true | Pexp_constraint ({pexp_desc = Pexp_pack _}, {ptyp_desc = Ptyp_package _}) -> false | Pexp_fun _ when ParsetreeViewer.isUnderscoreApplySugar rhs -> false diff --git a/jscomp/syntax/tests/printer/expr/expected/smartPipe.res.txt b/jscomp/syntax/tests/printer/expr/expected/smartPipe.res.txt index f67034fc4e..90b24b0144 100644 --- a/jscomp/syntax/tests/printer/expr/expected/smartPipe.res.txt +++ b/jscomp/syntax/tests/printer/expr/expected/smartPipe.res.txt @@ -31,3 +31,11 @@ let messages = React.useMemo(() => ->Array.filter(ChatMessage.isVisibleInSimpleFilter) ->Array.toSorted(ChatMessage.compareByDateAsc) , [messagesById]) + +f->(v => g(x))->g + +f->v->g + +x->(v => g(x))->f->(v => g(x)->k)->g + +f->(v => g(x)->k->(x => s(x)))->g diff --git a/jscomp/syntax/tests/printer/expr/smartPipe.res b/jscomp/syntax/tests/printer/expr/smartPipe.res index 0f1d03531f..2bc8183937 100644 --- a/jscomp/syntax/tests/printer/expr/smartPipe.res +++ b/jscomp/syntax/tests/printer/expr/smartPipe.res @@ -29,3 +29,10 @@ let messages = React.useMemo(() => ->Array.toSorted(ChatMessage.compareByDateAsc) , [messagesById]) +f->(v => g(x))->g + +f->(v)->g + +x->(v => g(x))->f->(v => g(x)->k)->g + +f->(v => g(x)->k->(x => s(x)))->g From 29644ec16e54a05f6e72047e33f068d232899aec Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Wed, 29 May 2024 18:20:06 +0200 Subject: [PATCH 4/4] Fix issue of incorrect switch cases with identical bodies when mixing object and array. Fixes https://github.com/rescript-lang/rescript-compiler/issues/6789 The issue happens when 2 cases, here `Object` and `Array`, have identical body (here `Console.log(v)`). The switch-generation code, which was not designed with untagged unions in mind, merges the two cases into one (and makes one of the two empty). However, for `Object` and `Array`, what's generated is not a straight switch, but a mix of `if-then-else` and `switch`. This means that the `Object` and `Array` cases are apart in the generated code, and merging them (making one empty) is wrong. # Conflicts: # CHANGELOG.md # jscomp/test/UntaggedVariants.js --- CHANGELOG.md | 1 + jscomp/core/lam_compile.ml | 22 ++++++++++++------- jscomp/test/UntaggedVariants.js | 37 ++++++++++++++++++++++++++++++++ jscomp/test/UntaggedVariants.res | 29 ++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b710211946..ad5d7801ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ #### :bug: Bug Fix +- Fix issue of incorrect switch cases with identical bodies when mixing object and array. https://github.com/rescript-lang/rescript-compiler/pull/6792 - Fix formatter eats comments on the first argument of a uncurried function. https://github.com/rescript-lang/rescript-compiler/pull/6763 - Fix formatter removes parens in pipe operator with anonymous uncurried function. https://github.com/rescript-lang/rescript-compiler/pull/6766 diff --git a/jscomp/core/lam_compile.ml b/jscomp/core/lam_compile.ml index 690f59a84f..70a10fc9fb 100644 --- a/jscomp/core/lam_compile.ml +++ b/jscomp/core/lam_compile.ml @@ -121,10 +121,10 @@ let morph_declare_to_assign (cxt : Lam_compile_context.t) k = k { cxt with continuation = Assign did } (Some (kind, did)) | _ -> k cxt None -let group_apply cases callback = +let group_apply ~merge_cases cases callback = Ext_list.flat_map - (Ext_list.stable_group cases (fun (_, lam) (_, lam1) -> - Lam.eq_approx lam lam1)) + (Ext_list.stable_group cases (fun (tag1, lam) (tag2, lam1) -> + merge_cases tag1 tag2 && Lam.eq_approx lam lam1)) (fun group -> Ext_list.map_last group callback) (* TODO: for expression generation, @@ -511,6 +511,7 @@ and compile_general_cases : _ -> ('a * J.case_clause) list -> J.statement) -> switch_exp: J.expression -> default: default_case -> + ?merge_cases: ('a -> 'a -> bool) -> ('a * Lam.t) list -> J.block = fun (type a) @@ -524,6 +525,7 @@ and compile_general_cases : ) ~(switch_exp : J.expression) ~(default : default_case) + ?(merge_cases = fun _ _ -> true) (cases : (a * Lam.t) list) -> match (cases, default) with | [], Default lam -> Js_output.output_as_block (compile_lambda cxt lam) @@ -586,7 +588,7 @@ and compile_general_cases : Some (Js_output.output_as_block (compile_lambda cxt lam)) in let body = - group_apply cases (fun last (switch_case, lam) -> + group_apply ~merge_cases cases (fun last (switch_case, lam) -> if last then (* merge and shared *) let switch_body, should_break = @@ -768,11 +770,12 @@ and compile_untagged_cases ~cxt ~switch_exp ~default ~block_cases cases = in E.emit_check check in - let is_not_typeof (l, _) = match l with - | Ast_untagged_variants.Untagged (InstanceType _) -> true - | _ -> false in + let tag_is_not_typeof = function + | Ast_untagged_variants.Untagged (InstanceType _) -> true + | _ -> false in + let clause_is_not_typeof (tag, _) = tag_is_not_typeof tag in let switch ?default ?declaration e clauses = - let (not_typeof_clauses, typeof_clauses) = List.partition is_not_typeof clauses in + let (not_typeof_clauses, typeof_clauses) = List.partition clause_is_not_typeof clauses in let rec build_if_chain remaining_clauses = (match remaining_clauses with | (Ast_untagged_variants.Untagged (InstanceType instanceType), {J.switch_body}) :: rest -> S.if_ (E.emit_check (IsInstanceOf (instanceType, Expr e))) @@ -780,6 +783,8 @@ and compile_untagged_cases ~cxt ~switch_exp ~default ~block_cases cases = ~else_:([build_if_chain rest]) | _ -> S.string_switch ?default ?declaration (E.typeof e) typeof_clauses) in build_if_chain not_typeof_clauses in + let merge_cases tag1 tag2 = (* only merge typeof cases, as instanceof cases are pulled out into if-then-else *) + not (tag_is_not_typeof tag1 || tag_is_not_typeof tag2) in cases |> compile_general_cases ~make_exp: E.tag_type ~eq_exp: mk_eq @@ -787,6 +792,7 @@ and compile_untagged_cases ~cxt ~switch_exp ~default ~block_cases cases = ~switch ~switch_exp ~default + ~merge_cases and compile_stringswitch l cases default (lambda_cxt : Lam_compile_context.t) = (* TODO might better optimization according to the number of cases diff --git a/jscomp/test/UntaggedVariants.js b/jscomp/test/UntaggedVariants.js index c0299611c4..b7ee19f8db 100644 --- a/jscomp/test/UntaggedVariants.js +++ b/jscomp/test/UntaggedVariants.js @@ -587,6 +587,42 @@ var OnlyOne = { onlyOne: "OnlyOne" }; +function should_not_merge(x) { + if (Array.isArray(x)) { + return "do not merge"; + } + if (x instanceof Date) { + return "do not merge"; + } + switch (typeof x) { + case "boolean" : + return "boolean"; + case "object" : + return "do not merge"; + + } +} + +function can_merge(x) { + if (Array.isArray(x)) { + return "do not merge"; + } + if (x instanceof Date) { + return "do not merge"; + } + switch (typeof x) { + case "boolean" : + case "object" : + return "merge"; + + } +} + +var MergeCases = { + should_not_merge: should_not_merge, + can_merge: can_merge +}; + var i = 42; var i2 = 42.5; @@ -634,4 +670,5 @@ exports.Arr = Arr; exports.AllInstanceofTypes = AllInstanceofTypes; exports.Aliased = Aliased; exports.OnlyOne = OnlyOne; +exports.MergeCases = MergeCases; /* l2 Not a pure module */ diff --git a/jscomp/test/UntaggedVariants.res b/jscomp/test/UntaggedVariants.res index 0bcfe81208..d49722195f 100644 --- a/jscomp/test/UntaggedVariants.res +++ b/jscomp/test/UntaggedVariants.res @@ -431,4 +431,31 @@ module Aliased = { module OnlyOne = { @unboxed type onlyOne = OnlyOne let onlyOne = OnlyOne -} \ No newline at end of file +} + +module MergeCases = { + type obj = {name: string} + + @unboxed + type t = + | Boolean(bool) + | Object(obj) + | Array(array) + | Date(Js.Date.t) + + let should_not_merge = x => + switch x { + | Object(_) => "do not merge" + | Array(_) => "do not merge" + | Date(_) => "do not merge" + | Boolean(_) => "boolean" + } + + let can_merge = x => + switch x { + | Object(_) => "merge" + | Array(_) => "do not merge" + | Date(_) => "do not merge" + | Boolean(_) => "merge" + } +}