@@ -105,6 +105,12 @@ module ErrorMessages = struct
105105 ]
106106 |> Doc. to_string ~width: 80
107107
108+ let experimental_let_unwrap_rec =
109+ " let? is not allowed to be recursive. Use a regular `let` or remove `rec`."
110+
111+ let experimental_let_unwrap_sig =
112+ " let? is not allowed in signatures. Use a regular `let` instead."
113+
108114 let type_param =
109115 " A type param consists of a singlequote followed by a name like `'a` or \
110116 `'A`"
@@ -2626,21 +2632,35 @@ and parse_attributes_and_binding (p : Parser.t) =
26262632 | _ -> []
26272633
26282634(* definition ::= let [rec] let-binding { and let-binding } *)
2629- and parse_let_bindings ~attrs ~start_pos p =
2630- Parser. optional p Let |> ignore;
2635+ and parse_let_bindings ~unwrap ~ attrs ~start_pos p =
2636+ Parser. optional p ( Let {unwrap}) |> ignore;
26312637 let rec_flag =
26322638 if Parser. optional p Token. Rec then Asttypes. Recursive
26332639 else Asttypes. Nonrecursive
26342640 in
2641+ let end_pos = p.Parser. start_pos in
2642+ if rec_flag = Asttypes. Recursive && unwrap then
2643+ Parser. err ~start_pos ~end_pos p
2644+ (Diagnostics. message ErrorMessages. experimental_let_unwrap_rec);
2645+ let add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs =
2646+ if unwrap then
2647+ ( {Asttypes. txt = " let.unwrap" ; loc = mk_loc start_pos end_pos},
2648+ Ast_payload. empty )
2649+ :: attrs
2650+ else attrs
2651+ in
2652+ let attrs = add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs in
26352653 let first = parse_let_binding_body ~start_pos ~attrs p in
26362654
26372655 let rec loop p bindings =
26382656 let start_pos = p.Parser. start_pos in
2657+ let end_pos = p.Parser. end_pos in
26392658 let attrs = parse_attributes_and_binding p in
2659+ let attrs = add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs in
26402660 match p.Parser. token with
26412661 | And ->
26422662 Parser. next p;
2643- ignore (Parser. optional p Let );
2663+ ignore (Parser. optional p ( Let {unwrap = false }) );
26442664 (* overparse for fault tolerance *)
26452665 let let_binding = parse_let_binding_body ~start_pos ~attrs p in
26462666 loop p (let_binding :: bindings)
@@ -3336,8 +3356,10 @@ and parse_expr_block_item p =
33363356 let block_expr = parse_expr_block p in
33373357 let loc = mk_loc start_pos p.prev_end_pos in
33383358 Ast_helper.Exp. open_ ~loc od.popen_override od.popen_lid block_expr
3339- | Let ->
3340- let rec_flag, let_bindings = parse_let_bindings ~attrs ~start_pos p in
3359+ | Let {unwrap} ->
3360+ let rec_flag, let_bindings =
3361+ parse_let_bindings ~unwrap ~attrs ~start_pos p
3362+ in
33413363 parse_newline_or_semicolon_expr_block p;
33423364 let next =
33433365 if Grammar. is_block_expr_start p.Parser. token then parse_expr_block p
@@ -3508,7 +3530,7 @@ and parse_if_or_if_let_expression p =
35083530 Parser. expect If p;
35093531 let expr =
35103532 match p.Parser. token with
3511- | Let ->
3533+ | Let _ ->
35123534 Parser. next p;
35133535 let if_let_expr = parse_if_let_expr start_pos p in
35143536 Parser. err ~start_pos: if_let_expr.pexp_loc.loc_start
@@ -5854,8 +5876,10 @@ and parse_structure_item_region p =
58545876 parse_newline_or_semicolon_structure p;
58555877 let loc = mk_loc start_pos p.prev_end_pos in
58565878 Some (Ast_helper.Str. open_ ~loc open_description)
5857- | Let ->
5858- let rec_flag, let_bindings = parse_let_bindings ~attrs ~start_pos p in
5879+ | Let {unwrap} ->
5880+ let rec_flag, let_bindings =
5881+ parse_let_bindings ~unwrap ~attrs ~start_pos p
5882+ in
58595883 parse_newline_or_semicolon_structure p;
58605884 let loc = mk_loc start_pos p.prev_end_pos in
58615885 Some (Ast_helper.Str. value ~loc rec_flag let_bindings)
@@ -6484,7 +6508,11 @@ and parse_signature_item_region p =
64846508 let start_pos = p.Parser. start_pos in
64856509 let attrs = parse_attributes p in
64866510 match p.Parser. token with
6487- | Let ->
6511+ | Let {unwrap} ->
6512+ if unwrap then (
6513+ Parser. err ~start_pos ~end_pos: p.Parser. end_pos p
6514+ (Diagnostics. message ErrorMessages. experimental_let_unwrap_sig);
6515+ Parser. next p);
64886516 Parser. begin_region p;
64896517 let value_desc = parse_sign_let_desc ~attrs p in
64906518 parse_newline_or_semicolon_signature p;
@@ -6684,7 +6712,7 @@ and parse_module_type_declaration ~attrs ~start_pos p =
66846712
66856713and parse_sign_let_desc ~attrs p =
66866714 let start_pos = p.Parser. start_pos in
6687- Parser. optional p Let |> ignore;
6715+ Parser. optional p ( Let {unwrap = false }) |> ignore;
66886716 let name, loc = parse_lident p in
66896717 let name = Location. mkloc name loc in
66906718 Parser. expect Colon p;
0 commit comments