@@ -110,6 +110,12 @@ module ErrorMessages = struct
110
110
]
111
111
|> Doc. to_string ~width: 80
112
112
113
+ let experimental_let_unwrap_rec =
114
+ " let? is not allowed to be recursive. Use a regular `let` or remove `rec`."
115
+
116
+ let experimental_let_unwrap_sig =
117
+ " let? is not allowed in signatures. Use a regular `let` instead."
118
+
113
119
let type_param =
114
120
" A type param consists of a singlequote followed by a name like `'a` or \
115
121
`'A`"
@@ -2689,21 +2695,35 @@ and parse_attributes_and_binding (p : Parser.t) =
2689
2695
| _ -> []
2690
2696
2691
2697
(* definition ::= let [rec] let-binding { and let-binding } *)
2692
- and parse_let_bindings ~attrs ~start_pos p =
2693
- Parser. optional p Let |> ignore;
2698
+ and parse_let_bindings ~unwrap ~ attrs ~start_pos p =
2699
+ Parser. optional p ( Let {unwrap}) |> ignore;
2694
2700
let rec_flag =
2695
2701
if Parser. optional p Token. Rec then Asttypes. Recursive
2696
2702
else Asttypes. Nonrecursive
2697
2703
in
2704
+ let end_pos = p.Parser. start_pos in
2705
+ if rec_flag = Asttypes. Recursive && unwrap then
2706
+ Parser. err ~start_pos ~end_pos p
2707
+ (Diagnostics. message ErrorMessages. experimental_let_unwrap_rec);
2708
+ let add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs =
2709
+ if unwrap then
2710
+ ( {Asttypes. txt = " let.unwrap" ; loc = mk_loc start_pos end_pos},
2711
+ Ast_payload. empty )
2712
+ :: attrs
2713
+ else attrs
2714
+ in
2715
+ let attrs = add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs in
2698
2716
let first = parse_let_binding_body ~start_pos ~attrs p in
2699
2717
2700
2718
let rec loop p bindings =
2701
2719
let start_pos = p.Parser. start_pos in
2720
+ let end_pos = p.Parser. end_pos in
2702
2721
let attrs = parse_attributes_and_binding p in
2722
+ let attrs = add_unwrap_attr ~unwrap ~start_pos ~end_pos attrs in
2703
2723
match p.Parser. token with
2704
2724
| And ->
2705
2725
Parser. next p;
2706
- ignore (Parser. optional p Let );
2726
+ ignore (Parser. optional p ( Let {unwrap = false }) );
2707
2727
(* overparse for fault tolerance *)
2708
2728
let let_binding = parse_let_binding_body ~start_pos ~attrs p in
2709
2729
loop p (let_binding :: bindings)
@@ -3437,8 +3457,10 @@ and parse_expr_block_item p =
3437
3457
let block_expr = parse_expr_block p in
3438
3458
let loc = mk_loc start_pos p.prev_end_pos in
3439
3459
Ast_helper.Exp. open_ ~loc od.popen_override od.popen_lid block_expr
3440
- | Let ->
3441
- let rec_flag, let_bindings = parse_let_bindings ~attrs ~start_pos p in
3460
+ | Let {unwrap} ->
3461
+ let rec_flag, let_bindings =
3462
+ parse_let_bindings ~unwrap ~attrs ~start_pos p
3463
+ in
3442
3464
parse_newline_or_semicolon_expr_block p;
3443
3465
let next =
3444
3466
if Grammar. is_block_expr_start p.Parser. token then parse_expr_block p
@@ -3609,7 +3631,7 @@ and parse_if_or_if_let_expression p =
3609
3631
Parser. expect If p;
3610
3632
let expr =
3611
3633
match p.Parser. token with
3612
- | Let ->
3634
+ | Let _ ->
3613
3635
Parser. next p;
3614
3636
let if_let_expr = parse_if_let_expr start_pos p in
3615
3637
Parser. err ~start_pos: if_let_expr.pexp_loc.loc_start
@@ -6008,8 +6030,10 @@ and parse_structure_item_region p =
6008
6030
parse_newline_or_semicolon_structure p;
6009
6031
let loc = mk_loc start_pos p.prev_end_pos in
6010
6032
Some (Ast_helper.Str. open_ ~loc open_description)
6011
- | Let ->
6012
- let rec_flag, let_bindings = parse_let_bindings ~attrs ~start_pos p in
6033
+ | Let {unwrap} ->
6034
+ let rec_flag, let_bindings =
6035
+ parse_let_bindings ~unwrap ~attrs ~start_pos p
6036
+ in
6013
6037
parse_newline_or_semicolon_structure p;
6014
6038
let loc = mk_loc start_pos p.prev_end_pos in
6015
6039
Some (Ast_helper.Str. value ~loc rec_flag let_bindings)
@@ -6638,7 +6662,11 @@ and parse_signature_item_region p =
6638
6662
let start_pos = p.Parser. start_pos in
6639
6663
let attrs = parse_attributes p in
6640
6664
match p.Parser. token with
6641
- | Let ->
6665
+ | Let {unwrap} ->
6666
+ if unwrap then (
6667
+ Parser. err ~start_pos ~end_pos: p.Parser. end_pos p
6668
+ (Diagnostics. message ErrorMessages. experimental_let_unwrap_sig);
6669
+ Parser. next p);
6642
6670
Parser. begin_region p;
6643
6671
let value_desc = parse_sign_let_desc ~attrs p in
6644
6672
parse_newline_or_semicolon_signature p;
@@ -6838,7 +6866,7 @@ and parse_module_type_declaration ~attrs ~start_pos p =
6838
6866
6839
6867
and parse_sign_let_desc ~attrs p =
6840
6868
let start_pos = p.Parser. start_pos in
6841
- Parser. optional p Let |> ignore;
6869
+ Parser. optional p ( Let {unwrap = false }) |> ignore;
6842
6870
let name, loc = parse_lident p in
6843
6871
let name = Location. mkloc name loc in
6844
6872
Parser. expect Colon p;
0 commit comments