diff --git a/CHANGELOG.md b/CHANGELOG.md index 491c004eb1..24b2589167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ #### :bug: Bug fix - Prevent lockfile creation when project folder is missing. https://github.com/rescript-lang/rescript/pull/7927 +- Fix parameter type / return type ambiguity error for unit case. https://github.com/rescript-lang/rescript/pull/7930 #### :memo: Documentation diff --git a/compiler/syntax/src/res_core.ml b/compiler/syntax/src/res_core.ml index 999743ac21..ee74eae6b4 100644 --- a/compiler/syntax/src/res_core.ml +++ b/compiler/syntax/src/res_core.ml @@ -2554,17 +2554,21 @@ and over_parse_constrained_or_coerced_or_arrow_expression p expr = | EqualGreater -> Parser.next p; let body = parse_expr p in - let pat = + let pat, expr_is_unit = match expr.pexp_desc with | Pexp_ident longident -> - Ast_helper.Pat.var ~loc:expr.pexp_loc - (Location.mkloc - (Longident.flatten longident.txt |> String.concat ".") - longident.loc) + ( Ast_helper.Pat.var ~loc:expr.pexp_loc + (Location.mkloc + (Longident.flatten longident.txt |> String.concat ".") + longident.loc), + false ) + | Pexp_construct (({txt = Longident.Lident "()"} as lid), None) -> + (Ast_helper.Pat.construct ~loc:expr.pexp_loc lid None, true) (* TODO: can we convert more expressions to patterns?*) | _ -> - Ast_helper.Pat.var ~loc:expr.pexp_loc - (Location.mkloc "pattern" expr.pexp_loc) + ( Ast_helper.Pat.var ~loc:expr.pexp_loc + (Location.mkloc "pattern" expr.pexp_loc), + false ) in let arrow1 = Ast_helper.Exp.fun_ @@ -2572,36 +2576,40 @@ and over_parse_constrained_or_coerced_or_arrow_expression p expr = ~arity:None Asttypes.Nolabel None pat (Ast_helper.Exp.constraint_ body typ) in - let arrow2 = - Ast_helper.Exp.fun_ - ~loc:(mk_loc expr.pexp_loc.loc_start body.pexp_loc.loc_end) - ~arity:None Asttypes.Nolabel None - (Ast_helper.Pat.constraint_ pat typ) - body - in - let msg = - Doc.breakable_group ~force_break:true - (Doc.concat - [ - Doc.text - "Did you mean to annotate the parameter type or the return \ - type?"; - Doc.indent - (Doc.concat - [ - Doc.line; - Doc.text "1) "; - ResPrinter.print_expression arrow1 CommentTable.empty; - Doc.line; - Doc.text "2) "; - ResPrinter.print_expression arrow2 CommentTable.empty; - ]); - ]) - |> Doc.to_string ~width:80 - in - Parser.err ~start_pos:expr.pexp_loc.loc_start - ~end_pos:body.pexp_loc.loc_end p (Diagnostics.message msg); - arrow1 + (* When the "expr" was `()`, the colon must apply to the return type, so + skip the ambiguity diagnostic and keep the parameter as unit. *) + if expr_is_unit then arrow1 + else + let arrow2 = + Ast_helper.Exp.fun_ + ~loc:(mk_loc expr.pexp_loc.loc_start body.pexp_loc.loc_end) + ~arity:None Asttypes.Nolabel None + (Ast_helper.Pat.constraint_ pat typ) + body + in + let msg = + Doc.breakable_group ~force_break:true + (Doc.concat + [ + Doc.text + "Did you mean to annotate the parameter type or the return \ + type?"; + Doc.indent + (Doc.concat + [ + Doc.line; + Doc.text "1) "; + ResPrinter.print_expression arrow1 CommentTable.empty; + Doc.line; + Doc.text "2) "; + ResPrinter.print_expression arrow2 CommentTable.empty; + ]); + ]) + |> Doc.to_string ~width:80 + in + Parser.err ~start_pos:expr.pexp_loc.loc_start + ~end_pos:body.pexp_loc.loc_end p (Diagnostics.message msg); + arrow1 | _ -> let loc = mk_loc expr.pexp_loc.loc_start typ.ptyp_loc.loc_end in let expr = Ast_helper.Exp.constraint_ ~loc expr typ in diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/arrow.res b/tests/syntax_tests/data/parsing/grammar/expressions/arrow.res index 9d37007aaf..e13dd438e7 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/arrow.res +++ b/tests/syntax_tests/data/parsing/grammar/expressions/arrow.res @@ -103,6 +103,8 @@ let un = (():u) type d<'a,'b> = ('a,'b) let c = (): d<'a,'b> => (1,2) +let arr = (): array> => [] + let fn = f => f; type f = int => unit; let a = fn(_ => (): f); \ No newline at end of file diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/expected/arrow.res.txt b/tests/syntax_tests/data/parsing/grammar/expressions/expected/arrow.res.txt index 8bb00c53d3..aa9afaab35 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/expected/arrow.res.txt +++ b/tests/syntax_tests/data/parsing/grammar/expressions/expected/arrow.res.txt @@ -74,6 +74,7 @@ type nonrec u = unit let un = (() : u) type nonrec ('a, 'b) d = ('a * 'b) let c [arity:1]() = ((1, 2) : ('a, 'b) d) +let arr () = ([||] : int nullable array) let fn [arity:1]f = f type nonrec f = int -> unit (a:1) let a = fn (fun [arity:1]_ -> () : f) \ No newline at end of file diff --git a/tests/syntax_tests/data/printer/expr/expected/fun.res.txt b/tests/syntax_tests/data/printer/expr/expected/fun.res.txt index 9821a0e93d..17b75d717e 100644 --- a/tests/syntax_tests/data/printer/expr/expected/fun.res.txt +++ b/tests/syntax_tests/data/printer/expr/expected/fun.res.txt @@ -356,3 +356,5 @@ let query = (~url, ()): (unit => unit => unit => unit) => { let f = a => b => a + b let f = (a, b) => (b, c) => a + b + c + d let f = (a, b) => (b, c) => (e, f, g) => a + b + c + d + e + f + g + +let unitConstraint = (): array> => [] diff --git a/tests/syntax_tests/data/printer/expr/fun.res b/tests/syntax_tests/data/printer/expr/fun.res index 2c5c5009af..af8700a6ed 100644 --- a/tests/syntax_tests/data/printer/expr/fun.res +++ b/tests/syntax_tests/data/printer/expr/fun.res @@ -297,3 +297,5 @@ let query = (~url, ()): (unit => unit => unit => unit) => { let f = (. a) => (. b) => a + b let f = (. a, b) => (. b, c) => a + b + c + d let f = (. a, b) => (. b , c) => (. e , f, g) => a + b + c + d + e + f + g + +let unitConstraint = (): array> => []