Skip to content

Commit e3eecdc

Browse files
committed
Fix parameter type / return type ambiguity error for unit case
1 parent 57c696b commit e3eecdc

File tree

5 files changed

+53
-37
lines changed

5 files changed

+53
-37
lines changed

compiler/syntax/src/res_core.ml

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,54 +2554,63 @@ and over_parse_constrained_or_coerced_or_arrow_expression p expr =
25542554
| EqualGreater ->
25552555
Parser.next p;
25562556
let body = parse_expr p in
2557-
let pat =
2557+
let pat, expr_is_unit =
25582558
match expr.pexp_desc with
25592559
| Pexp_ident longident ->
2560-
Ast_helper.Pat.var ~loc:expr.pexp_loc
2561-
(Location.mkloc
2562-
(Longident.flatten longident.txt |> String.concat ".")
2563-
longident.loc)
2560+
( Ast_helper.Pat.var ~loc:expr.pexp_loc
2561+
(Location.mkloc
2562+
(Longident.flatten longident.txt |> String.concat ".")
2563+
longident.loc)
2564+
, false )
2565+
| Pexp_construct ({txt = Longident.Lident "()"} as lid, None) ->
2566+
(Ast_helper.Pat.construct ~loc:expr.pexp_loc lid None, true)
25642567
(* TODO: can we convert more expressions to patterns?*)
25652568
| _ ->
2566-
Ast_helper.Pat.var ~loc:expr.pexp_loc
2567-
(Location.mkloc "pattern" expr.pexp_loc)
2569+
( Ast_helper.Pat.var ~loc:expr.pexp_loc
2570+
(Location.mkloc "pattern" expr.pexp_loc)
2571+
, false )
25682572
in
25692573
let arrow1 =
25702574
Ast_helper.Exp.fun_
25712575
~loc:(mk_loc expr.pexp_loc.loc_start body.pexp_loc.loc_end)
25722576
~arity:None Asttypes.Nolabel None pat
25732577
(Ast_helper.Exp.constraint_ body typ)
25742578
in
2575-
let arrow2 =
2576-
Ast_helper.Exp.fun_
2577-
~loc:(mk_loc expr.pexp_loc.loc_start body.pexp_loc.loc_end)
2578-
~arity:None Asttypes.Nolabel None
2579-
(Ast_helper.Pat.constraint_ pat typ)
2580-
body
2581-
in
2582-
let msg =
2583-
Doc.breakable_group ~force_break:true
2584-
(Doc.concat
2585-
[
2586-
Doc.text
2587-
"Did you mean to annotate the parameter type or the return \
2588-
type?";
2589-
Doc.indent
2590-
(Doc.concat
2591-
[
2592-
Doc.line;
2593-
Doc.text "1) ";
2594-
ResPrinter.print_expression arrow1 CommentTable.empty;
2595-
Doc.line;
2596-
Doc.text "2) ";
2597-
ResPrinter.print_expression arrow2 CommentTable.empty;
2598-
]);
2599-
])
2600-
|> Doc.to_string ~width:80
2601-
in
2602-
Parser.err ~start_pos:expr.pexp_loc.loc_start
2603-
~end_pos:body.pexp_loc.loc_end p (Diagnostics.message msg);
2604-
arrow1
2579+
(* When the "expr" was `()`, the colon must apply to the return type, so
2580+
skip the ambiguity diagnostic and keep the parameter as unit. *)
2581+
if expr_is_unit then
2582+
arrow1
2583+
else (
2584+
let arrow2 =
2585+
Ast_helper.Exp.fun_
2586+
~loc:(mk_loc expr.pexp_loc.loc_start body.pexp_loc.loc_end)
2587+
~arity:None Asttypes.Nolabel None
2588+
(Ast_helper.Pat.constraint_ pat typ)
2589+
body
2590+
in
2591+
let msg =
2592+
Doc.breakable_group ~force_break:true
2593+
(Doc.concat
2594+
[
2595+
Doc.text
2596+
"Did you mean to annotate the parameter type or the return \
2597+
type?";
2598+
Doc.indent
2599+
(Doc.concat
2600+
[
2601+
Doc.line;
2602+
Doc.text "1) ";
2603+
ResPrinter.print_expression arrow1 CommentTable.empty;
2604+
Doc.line;
2605+
Doc.text "2) ";
2606+
ResPrinter.print_expression arrow2 CommentTable.empty;
2607+
]);
2608+
])
2609+
|> Doc.to_string ~width:80
2610+
in
2611+
Parser.err ~start_pos:expr.pexp_loc.loc_start
2612+
~end_pos:body.pexp_loc.loc_end p (Diagnostics.message msg);
2613+
arrow1)
26052614
| _ ->
26062615
let loc = mk_loc expr.pexp_loc.loc_start typ.ptyp_loc.loc_end in
26072616
let expr = Ast_helper.Exp.constraint_ ~loc expr typ in

tests/syntax_tests/data/parsing/grammar/expressions/arrow.res

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ let un = (():u)
103103
type d<'a,'b> = ('a,'b)
104104
let c = (): d<'a,'b> => (1,2)
105105

106+
let arr = (): array<nullable<int>> => []
107+
106108
let fn = f => f;
107109
type f = int => unit;
108110
let a = fn(_ => (): f);

tests/syntax_tests/data/parsing/grammar/expressions/expected/arrow.res.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type nonrec u = unit
7474
let un = (() : u)
7575
type nonrec ('a, 'b) d = ('a * 'b)
7676
let c [arity:1]() = ((1, 2) : ('a, 'b) d)
77+
let arr () = ([||] : int nullable array)
7778
let fn [arity:1]f = f
7879
type nonrec f = int -> unit (a:1)
7980
let a = fn (fun [arity:1]_ -> () : f)

tests/syntax_tests/data/printer/expr/expected/fun.res.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,5 @@ let query = (~url, ()): (unit => unit => unit => unit) => {
356356
let f = a => b => a + b
357357
let f = (a, b) => (b, c) => a + b + c + d
358358
let f = (a, b) => (b, c) => (e, f, g) => a + b + c + d + e + f + g
359+
360+
let unitConstraint = (): array<nullable<int>> => []

tests/syntax_tests/data/printer/expr/fun.res

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,5 @@ let query = (~url, ()): (unit => unit => unit => unit) => {
297297
let f = (. a) => (. b) => a + b
298298
let f = (. a, b) => (. b, c) => a + b + c + d
299299
let f = (. a, b) => (. b , c) => (. e , f, g) => a + b + c + d + e + f + g
300+
301+
let unitConstraint = (): array<nullable<int>> => []

0 commit comments

Comments
 (0)