From 3cd76e21163edfda8b662d7071687180a4143ba2 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno <cristianoc@users.noreply.github.com> Date: Sat, 4 Feb 2023 10:56:07 +0100 Subject: [PATCH] Fix issue with error messages for uncurried functions where expected and given type were swapped The logic for unification for `Function$`, which unifies with a generic uncurried type, was swapped. The error message for arity mismatch was also swapped, so those errors were showing correctly. However, in the case of expected curried function, when given a curried function whose type is begin inferred, the error message was swapped. Also added a specialized error message when the uncurried type only contains a type variable, so `$function<'a, ...>` does not leak in the output. This happens as unification failt early, and the type of the function has not been determined yet. --- CHANGELOG.md | 1 + .../expected/curried_expected.res.expected | 10 ++++++++++ .../super_errors/fixtures/curried_expected.res | 3 +++ jscomp/ml/typecore.ml | 2 +- jscomp/super_errors/super_typecore.ml | 9 +++++++-- 5 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 jscomp/build_tests/super_errors/expected/curried_expected.res.expected create mode 100644 jscomp/build_tests/super_errors/fixtures/curried_expected.res diff --git a/CHANGELOG.md b/CHANGELOG.md index d200abbc6b..3bdf0eb9a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ These are only breaking changes for unformatted code. - Fix issue where error messages related to non-existent props were displayed without location information https://github.com/rescript-lang/rescript-compiler/pull/5960 - Fix type inference issue with uncurried functions applied to a single unit argument. The issue was introduced in https://github.com/rescript-lang/rescript-compiler/pull/5907 when adding support to `foo()` when `foo` has only optional arguments. https://github.com/rescript-lang/rescript-compiler/pull/5970 - 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 #### :nail_care: Polish diff --git a/jscomp/build_tests/super_errors/expected/curried_expected.res.expected b/jscomp/build_tests/super_errors/expected/curried_expected.res.expected new file mode 100644 index 0000000000..5b789c5abb --- /dev/null +++ b/jscomp/build_tests/super_errors/expected/curried_expected.res.expected @@ -0,0 +1,10 @@ + + [1;31mWe've found a bug for you![0m + [36m/.../fixtures/curried_expected.res[0m:[2m3:24-38[0m + + 1 [2m│[0m let expectCurried = f => f(1) + 2 + 2 [2m│[0m + [1;31m3[0m [2m│[0m let z1 = expectCurried([1;31m(. x, y) => x+y[0m) + 4 [2m│[0m + + This function is an uncurried function where a curried function is expected \ No newline at end of file diff --git a/jscomp/build_tests/super_errors/fixtures/curried_expected.res b/jscomp/build_tests/super_errors/fixtures/curried_expected.res new file mode 100644 index 0000000000..224d432a15 --- /dev/null +++ b/jscomp/build_tests/super_errors/fixtures/curried_expected.res @@ -0,0 +1,3 @@ +let expectCurried = f => f(1) + 2 + +let z1 = expectCurried((. x, y) => x+y) diff --git a/jscomp/ml/typecore.ml b/jscomp/ml/typecore.ml index 4dc62db56b..acdd846da4 100644 --- a/jscomp/ml/typecore.ml +++ b/jscomp/ml/typecore.ml @@ -2107,7 +2107,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = let state = Warnings.backup () in let arity = Ast_uncurried.attributes_to_arity sexp.pexp_attributes in let uncurried_typ = Ast_uncurried.make_uncurried_type ~env ~arity (newvar()) in - unify_exp_types loc env ty_expected uncurried_typ; + unify_exp_types loc env uncurried_typ ty_expected; (* Disable Unerasable_optional_argument for uncurried functions *) let unerasable_optional_argument = Warnings.number Unerasable_optional_argument in Warnings.parse_options false ("-" ^ string_of_int unerasable_optional_argument); diff --git a/jscomp/super_errors/super_typecore.ml b/jscomp/super_errors/super_typecore.ml index cef6a7ec0a..0f99ca1f0e 100644 --- a/jscomp/super_errors/super_typecore.ml +++ b/jscomp/super_errors/super_typecore.ml @@ -121,9 +121,9 @@ end let reportArityMismatch ~arityA ~arityB ppf = fprintf ppf "This function expected @{<info>%s@} %s, but got @{<error>%s@}" - arityA - (if arityA = "1" then "argument" else "arguments") arityB + (if arityB = "1" then "argument" else "arguments") + arityA (* Pasted from typecore.ml. Needed for some cases in report_error below *) (* Records *) @@ -169,6 +169,11 @@ let report_error env ppf = function (_, {desc = Tconstr (Pident {name = "function$"},_,_)}) :: _ ) -> fprintf ppf "This function is a curried function where an uncurried function is expected" + | Expr_type_clash ( + (_, {desc = Tconstr (Pident {name = "function$"}, [{desc=Tvar _}; _],_)}) :: + (_, {desc = Tarrow _}) :: _ + ) -> + fprintf ppf "This function is an uncurried function where a curried function is expected" | Expr_type_clash ( (_, {desc = Tconstr (Pident {name = "function$"},[_; tA],_)}) :: (_, {desc = Tconstr (Pident {name = "function$"},[_; tB],_)}) :: _