@@ -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`"
@@ -2518,21 +2524,35 @@ and parse_attributes_and_binding (p : Parser.t) =
25182524 | _ -> []
25192525
25202526(* definition ::= let [rec] let-binding { and let-binding } *)
2521- and parse_let_bindings ~attrs ~start_pos p =
2522- Parser. optional p Let |> ignore;
2527+ and parse_let_bindings ~unwrap ~ attrs ~start_pos p =
2528+ Parser. optional p ( Let {unwrap}) |> ignore;
25232529 let rec_flag =
25242530 if Parser. optional p Token. Rec then Asttypes. Recursive
25252531 else Asttypes. Nonrecursive
25262532 in
2533+ let end_pos = p.Parser. start_pos in
2534+ if rec_flag = Asttypes. Recursive && unwrap then
2535+ Parser. err ~start_pos ~end_pos p
2536+ (Diagnostics. message ErrorMessages. experimental_let_unwrap_rec);
2537+ let add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs =
2538+ if unwrap then
2539+ ( {Asttypes. txt = " let.unwrap" ; loc = mk_loc start_pos end_pos},
2540+ Ast_payload. empty )
2541+ :: attrs
2542+ else attrs
2543+ in
2544+ let attrs = add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs in
25272545 let first = parse_let_binding_body ~start_pos ~attrs p in
25282546
25292547 let rec loop p bindings =
25302548 let start_pos = p.Parser. start_pos in
2549+ let end_pos = p.Parser. end_pos in
25312550 let attrs = parse_attributes_and_binding p in
2551+ let attrs = add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs in
25322552 match p.Parser. token with
25332553 | And ->
25342554 Parser. next p;
2535- ignore (Parser. optional p Let );
2555+ ignore (Parser. optional p ( Let {unwrap = false }) );
25362556 (* overparse for fault tolerance *)
25372557 let let_binding = parse_let_binding_body ~start_pos ~attrs p in
25382558 loop p (let_binding :: bindings)
@@ -3275,8 +3295,10 @@ and parse_expr_block_item p =
32753295 let block_expr = parse_expr_block p in
32763296 let loc = mk_loc start_pos p.prev_end_pos in
32773297 Ast_helper.Exp. open_ ~loc od.popen_override od.popen_lid block_expr
3278- | Let ->
3279- let rec_flag, let_bindings = parse_let_bindings ~attrs ~start_pos p in
3298+ | Let {unwrap} ->
3299+ let rec_flag, let_bindings =
3300+ parse_let_bindings ~unwrap ~attrs ~start_pos p
3301+ in
32803302 parse_newline_or_semicolon_expr_block p;
32813303 let next =
32823304 if Grammar. is_block_expr_start p.Parser. token then parse_expr_block p
@@ -3447,7 +3469,7 @@ and parse_if_or_if_let_expression p =
34473469 Parser. expect If p;
34483470 let expr =
34493471 match p.Parser. token with
3450- | Let ->
3472+ | Let _ ->
34513473 Parser. next p;
34523474 let if_let_expr = parse_if_let_expr start_pos p in
34533475 Parser. err ~start_pos: if_let_expr.pexp_loc.loc_start
@@ -5787,8 +5809,10 @@ and parse_structure_item_region p =
57875809 parse_newline_or_semicolon_structure p;
57885810 let loc = mk_loc start_pos p.prev_end_pos in
57895811 Some (Ast_helper.Str. open_ ~loc open_description)
5790- | Let ->
5791- let rec_flag, let_bindings = parse_let_bindings ~attrs ~start_pos p in
5812+ | Let {unwrap} ->
5813+ let rec_flag, let_bindings =
5814+ parse_let_bindings ~unwrap ~attrs ~start_pos p
5815+ in
57925816 parse_newline_or_semicolon_structure p;
57935817 let loc = mk_loc start_pos p.prev_end_pos in
57945818 Some (Ast_helper.Str. value ~loc rec_flag let_bindings)
@@ -6417,7 +6441,11 @@ and parse_signature_item_region p =
64176441 let start_pos = p.Parser. start_pos in
64186442 let attrs = parse_attributes p in
64196443 match p.Parser. token with
6420- | Let ->
6444+ | Let {unwrap} ->
6445+ if unwrap then (
6446+ Parser. err ~start_pos ~end_pos: p.Parser. end_pos p
6447+ (Diagnostics. message ErrorMessages. experimental_let_unwrap_sig);
6448+ Parser. next p);
64216449 Parser. begin_region p;
64226450 let value_desc = parse_sign_let_desc ~attrs p in
64236451 parse_newline_or_semicolon_signature p;
@@ -6617,7 +6645,7 @@ and parse_module_type_declaration ~attrs ~start_pos p =
66176645
66186646and parse_sign_let_desc ~attrs p =
66196647 let start_pos = p.Parser. start_pos in
6620- Parser. optional p Let |> ignore;
6648+ Parser. optional p ( Let {unwrap = false }) |> ignore;
66216649 let name, loc = parse_lident p in
66226650 let name = Location. mkloc name loc in
66236651 Parser. expect Colon p;
0 commit comments