diff --git a/CHANGES.md b/CHANGES.md index 457deabcbe..1638394bd4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,8 @@ Tags: ### Changed +- Compatible with OCaml 5.1.0 (#2412, @Julow) + The syntax of let-bindings changed sligthly in this version. - \* Consistent formatting of arrows in class types (#2422, @Julow) ### Fixed diff --git a/lib/Ast.ml b/lib/Ast.ml index bbbf82be01..c190ce6e02 100644 --- a/lib/Ast.ml +++ b/lib/Ast.ml @@ -263,7 +263,7 @@ and mod_is_simple x = | Pmod_structure (_ :: _) | Pmod_extension _ | Pmod_functor (_, _) -> false | Pmod_constraint (e, t) -> mod_is_simple e && mty_is_simple t | Pmod_apply (a, b) -> mod_is_simple a && mod_is_simple b - | Pmod_gen_apply (a, _) -> mod_is_simple a + | Pmod_apply_unit (a, _) -> mod_is_simple a module Mty = struct let is_simple = mty_is_simple @@ -319,7 +319,7 @@ module Structure_item = struct match itm.pstr_desc with | Pstr_attribute atr -> Attr.is_doc atr | Pstr_eval (_, atrs) - |Pstr_value {lbs_bindings= {lb_attributes= atrs; _} :: _; _} + |Pstr_value {pvbs_bindings= {pvb_attributes= atrs; _} :: _; _} |Pstr_primitive {pval_attributes= atrs; _} |Pstr_type (_, {ptype_attributes= atrs; _} :: _) |Pstr_typext {ptyext_attributes= atrs; _} @@ -339,7 +339,7 @@ module Structure_item = struct |Pstr_module {pmb_attributes= atrs1; pmb_expr= {pmod_attributes= atrs2; _}; _} -> List.exists ~f:Attr.is_doc atrs1 || List.exists ~f:Attr.is_doc atrs2 - | Pstr_value {lbs_bindings= []; _} + | Pstr_value {pvbs_bindings= []; _} |Pstr_type (_, []) |Pstr_recmodule [] |Pstr_class_type [] @@ -356,7 +356,7 @@ module Structure_item = struct let rec is_simple_mod me = match me.pmod_desc with | Pmod_apply (me1, me2) -> is_simple_mod me1 && is_simple_mod me2 - | Pmod_functor (_, me) | Pmod_gen_apply (me, _) -> + | Pmod_functor (_, me) | Pmod_apply_unit (me, _) -> is_simple_mod me | Pmod_ident i -> longident_is_simple c i.txt | _ -> false @@ -493,14 +493,14 @@ module Signature_item = struct end module Lb = struct - let has_doc itm = List.exists ~f:Attr.is_doc itm.lb_attributes + let has_doc itm = List.exists ~f:Attr.is_doc itm.pvb_attributes let is_simple (i, (c : Conf.t)) = Poly.(c.fmt_opts.module_item_spacing.v = `Compact) - && Location.is_single_line i.lb_loc c.fmt_opts.margin.v + && Location.is_single_line i.pvb_loc c.fmt_opts.margin.v let break_between s cc (i1, c1) (i2, c2) = - cmts_between s cc i1.lb_loc i2.lb_loc + cmts_between s cc i1.pvb_loc i2.pvb_loc || has_doc i1 || has_doc i2 || (not (is_simple (i1, c1))) || not (is_simple (i2, c2)) @@ -623,7 +623,7 @@ module T = struct | Cty of class_type | Pat of pattern | Exp of expression - | Lb of let_binding + | Lb of value_binding | Mb of module_binding | Md of module_declaration | Cl of class_expr @@ -643,7 +643,7 @@ module T = struct | Td t -> Format.fprintf fs "Td:@\n%a" Printast.type_declaration t | Pat p -> Format.fprintf fs "Pat:@\n%a" Printast.pattern p | Exp e -> Format.fprintf fs "Exp:@\n%a" Printast.expression e - | Lb b -> Format.fprintf fs "Lb:@\n%a" Printast.let_binding b + | Lb b -> Format.fprintf fs "Lb:@\n%a" Printast.value_binding b | Mb m -> Format.fprintf fs "Mb:@\n%a" Printast.module_binding m | Md m -> Format.fprintf fs "Md:@\n%a" Printast.module_declaration m | Cl cl -> Format.fprintf fs "Cl:@\n%a" Printast.class_expr cl @@ -673,7 +673,7 @@ let attributes = function | Cty x -> x.pcty_attributes | Pat x -> x.ppat_attributes | Exp x -> x.pexp_attributes - | Lb x -> x.lb_attributes + | Lb x -> x.pvb_attributes | Mb x -> x.pmb_attributes | Md x -> x.pmd_attributes | Cl x -> x.pcl_attributes @@ -694,7 +694,7 @@ let location = function | Cty x -> x.pcty_loc | Pat x -> x.ppat_loc | Exp x -> x.pexp_loc - | Lb x -> x.lb_loc + | Lb x -> x.pvb_loc | Mb x -> x.pmb_loc | Md x -> x.pmd_loc | Cl x -> x.pcl_loc @@ -887,6 +887,16 @@ end = struct List.exists t ~f:(fun x -> x.pap_type == typ) | _ -> false ) in + let check_pvb pvb = + match pvb.pvb_constraint with + | Some (Pvc_constraint {typ= typ'; _}) -> typ' == typ + | Some (Pvc_coercion {ground; coercion}) -> + coercion == typ || Option.exists ground ~f:(fun x -> x == typ) + | None -> false + in + let check_let_bindings lbs = + List.exists lbs.pvbs_bindings ~f:check_pvb + in match ctx with | Pld (PTyp t1) -> assert (typ == t1) | Pld _ -> assert false @@ -956,6 +966,7 @@ end = struct assert ( List.exists en1 ~f:(fun (_, (t1, t2), _) -> Option.exists t1 ~f || Option.exists t2 ~f ) ) + | Pexp_let (lbs, _) -> assert (check_let_bindings lbs) | _ -> assert false ) | Lb _ -> assert false | Mb _ -> assert false @@ -965,7 +976,7 @@ end = struct match pcl_desc with | Pcl_constr (_, l) -> List.exists l ~f | Pcl_constraint _ -> false - | Pcl_let _ -> false + | Pcl_let (lbs, _) -> check_let_bindings lbs | Pcl_apply _ -> false | Pcl_fun _ -> false | Pcl_open _ -> false @@ -1005,6 +1016,16 @@ end = struct | Pstr_class_type l -> assert (check_class_type l) | Pstr_extension ((_, PTyp t), _) -> assert (t == typ) | Pstr_extension (_, _) -> assert false + | Pstr_value {pvbs_bindings; _} -> + let check_pvb pvb = + match pvb.pvb_constraint with + | Some (Pvc_constraint {typ= typ'; _}) -> typ' == typ + | Some (Pvc_coercion {ground; coercion}) -> + coercion == typ + || Option.exists ground ~f:(fun x -> x == typ) + | None -> false + in + assert (List.exists pvbs_bindings ~f:check_pvb) | _ -> assert false ) | Clf {pcf_desc; _} -> assert ( @@ -1188,7 +1209,7 @@ end = struct | _ -> false in let check_bindings l = - List.exists l ~f:(fun {lb_pattern; _} -> check_subpat lb_pattern) + List.exists l ~f:(fun {pvb_pat; _} -> check_subpat pvb_pat) in match ctx with | Pld (PPat (p1, _)) -> assert (p1 == pat) @@ -1236,8 +1257,8 @@ end = struct | Pexp_extension (_, ext) -> assert (check_extensions ext) | Pexp_object {pcstr_self; _} -> assert (Option.exists ~f:(fun self_ -> self_ == pat) pcstr_self) - | Pexp_let ({lbs_bindings; _}, _) -> - assert (check_bindings lbs_bindings) + | Pexp_let ({pvbs_bindings; _}, _) -> + assert (check_bindings pvbs_bindings) | Pexp_letop {let_; ands; _} -> let f {pbop_pat; _} = check_subpat pbop_pat in assert (f let_ || List.exists ~f ands) @@ -1248,7 +1269,7 @@ end = struct | _ -> false ) ) | Pexp_for (p, _, _, _, _) | Pexp_fun (_, _, p, _) -> assert (p == pat) ) - | Lb x -> assert (x.lb_pattern == pat) + | Lb x -> assert (x.pvb_pat == pat) | Mb _ -> assert false | Md _ -> assert false | Cl ctx -> @@ -1259,7 +1280,7 @@ end = struct | Pcl_structure {pcstr_self; _} -> Option.exists ~f:(fun self_ -> self_ == pat) pcstr_self | Pcl_apply _ -> false - | Pcl_let ({lbs_bindings; _}, _) -> check_bindings lbs_bindings + | Pcl_let ({pvbs_bindings; _}, _) -> check_bindings pvbs_bindings | Pcl_constraint _ -> false | Pcl_extension (_, ext) -> check_extensions ext | Pcl_open _ -> false ) @@ -1267,7 +1288,7 @@ end = struct | Mty _ | Mod _ | Sig _ -> assert false | Str str -> ( match str.pstr_desc with - | Pstr_value {lbs_bindings; _} -> assert (check_bindings lbs_bindings) + | Pstr_value {pvbs_bindings; _} -> assert (check_bindings pvbs_bindings) | Pstr_extension ((_, ext), _) -> assert (check_extensions ext) | _ -> assert false ) | Clf {pcf_desc; _} -> @@ -1306,10 +1327,10 @@ end = struct |Pexp_unreachable | Pexp_hole -> assert false | Pexp_object _ -> assert false - | Pexp_let ({lbs_bindings; _}, e) -> + | Pexp_let ({pvbs_bindings; _}, e) -> assert ( - List.exists lbs_bindings ~f:(fun {lb_expression; _} -> - lb_expression == exp ) + List.exists pvbs_bindings ~f:(fun {pvb_expr; _} -> + pvb_expr == exp ) || e == exp ) | Pexp_letop {let_; ands; body} -> let f {pbop_exp; _} = pbop_exp == exp in @@ -1372,16 +1393,16 @@ end = struct | Pexp_for (_, e1, e2, _, e3) -> assert (e1 == exp || e2 == exp || e3 == exp) | Pexp_override e1N -> assert (List.exists e1N ~f:snd_f) ) - | Lb x -> assert (x.lb_expression == exp) + | Lb x -> assert (x.pvb_expr == exp) | Mb _ -> assert false | Md _ -> assert false | Str str -> ( match str.pstr_desc with | Pstr_eval (e0, _) -> assert (e0 == exp) - | Pstr_value {lbs_bindings; _} -> + | Pstr_value {pvbs_bindings; _} -> assert ( - List.exists lbs_bindings ~f:(fun {lb_expression; _} -> - lb_expression == exp ) ) + List.exists pvbs_bindings ~f:(fun {pvb_expr; _} -> + pvb_expr == exp ) ) | Pstr_extension ((_, ext), _) -> assert (check_extensions ext) | Pstr_primitive _ | Pstr_type _ | Pstr_typext _ | Pstr_exception _ |Pstr_module _ | Pstr_recmodule _ | Pstr_modtype _ | Pstr_open _ @@ -1397,9 +1418,9 @@ end = struct | Pcl_constr _ -> false | Pcl_structure _ -> false | Pcl_apply (_, l) -> List.exists l ~f:(fun (_, e) -> e == exp) - | Pcl_let ({lbs_bindings; _}, _) -> - List.exists lbs_bindings ~f:(fun {lb_expression; _} -> - lb_expression == exp ) + | Pcl_let ({pvbs_bindings; _}, _) -> + List.exists pvbs_bindings ~f:(fun {pvb_expr; _} -> + pvb_expr == exp ) | Pcl_constraint _ -> false | Pcl_extension _ -> false | Pcl_open _ -> false @@ -1797,8 +1818,16 @@ end = struct (* The RHS of an application is always parenthesized already. *) | Mod {pmod_desc= Pmod_apply (_, x); _}, Pmod_functor _ when m == x -> false - | Mod {pmod_desc= Pmod_apply _; _}, Pmod_functor _ -> true - | Mod {pmod_desc= Pmod_gen_apply _; _}, Pmod_functor _ -> true + | Mod {pmod_desc= Pmod_apply _ | Pmod_apply_unit _; _}, Pmod_functor _ -> + true + | _ -> false + + (* Whether a pattern should be parenthesed if followed by a [:]. *) + let exposed_right_colon pat = + match pat.ppat_desc with + (* Some patterns that are always parenthesed are not mentionned here: + Ppat_constraint, Ppat_unpack *) + | Ppat_tuple _ -> true | _ -> false (** [parenze_pat {ctx; ast}] holds when pattern [ast] should be @@ -1817,20 +1846,15 @@ end = struct | Ppat_construct _ | Ppat_record _ | Ppat_variant _ -> false | _ -> true ) | Pat {ppat_desc= Ppat_construct _; _}, Ppat_cons _ -> true - | ( ( Exp {pexp_desc= Pexp_let _ | Pexp_letop _; _} - | Str {pstr_desc= Pstr_value _; _} ) + | _, Ppat_constraint (_, {ptyp_desc= Ptyp_poly _; _}) -> false + | ( Exp {pexp_desc= Pexp_letop _; _} , ( Ppat_construct (_, Some _) | Ppat_cons _ | Ppat_variant (_, Some _) - | Ppat_or _ | Ppat_alias _ ) ) -> + | Ppat_or _ | Ppat_alias _ + | Ppat_constraint ({ppat_desc= Ppat_any; _}, _) ) ) -> true - | _, Ppat_constraint (_, {ptyp_desc= Ptyp_poly _; _}) -> false - | ( ( Exp {pexp_desc= Pexp_let _ | Pexp_letop _; _} - | Str {pstr_desc= Pstr_value _; _} ) - , Ppat_constraint ({ppat_desc= Ppat_any; _}, _) ) -> - true - | ( ( Exp {pexp_desc= Pexp_let _ | Pexp_letop _; _} - | Str {pstr_desc= Pstr_value _; _} ) + | ( Exp {pexp_desc= Pexp_letop _; _} , Ppat_constraint ({ppat_desc= Ppat_tuple _; _}, _) ) -> false | _, Ppat_constraint _ @@ -1868,7 +1892,7 @@ end = struct |Cl {pcl_desc= Pcl_fun _; _}, Ppat_construct _ |Cl {pcl_desc= Pcl_fun _; _}, Ppat_alias _ |Cl {pcl_desc= Pcl_fun _; _}, Ppat_lazy _ - |Exp {pexp_desc= Pexp_let _ | Pexp_letop _; _}, Ppat_exception _ + |Exp {pexp_desc= Pexp_letop _; _}, Ppat_exception _ |( Exp {pexp_desc= Pexp_fun _; _} , ( Ppat_construct _ | Ppat_cons _ | Ppat_lazy _ | Ppat_tuple _ | Ppat_variant _ ) ) -> @@ -1878,14 +1902,24 @@ end = struct , (Ppat_construct (_, Some _) | Ppat_cons _ | Ppat_variant (_, Some _)) ) -> true - | ( ( Exp {pexp_desc= Pexp_let ({lbs_bindings; _}, _); _} - | Str {pstr_desc= Pstr_value {lbs_bindings; _}; _} ) - , _ ) -> - List.exists lbs_bindings ~f:(function - | {lb_pattern; lb_expression= {pexp_desc= Pexp_constraint _; _}; _} - -> - lb_pattern == pat - | _ -> false ) + | _, Ppat_var _ when List.is_empty pat.ppat_attributes -> false + | ( ( Exp {pexp_desc= Pexp_let ({pvbs_bindings; _}, _); _} + | Str {pstr_desc= Pstr_value {pvbs_bindings; _}; _} ) + , pat_desc ) -> ( + match pat_desc with + | Ppat_construct (_, Some _) + |Ppat_variant (_, Some _) + |Ppat_cons _ | Ppat_alias _ | Ppat_constraint _ | Ppat_lazy _ + |Ppat_or _ -> + (* Add disambiguation parentheses that are not necessary. *) + true + | _ when exposed_right_colon pat -> + (* Some patterns must be parenthesed when followed by a colon. *) + let pvb = + List.find_exn pvbs_bindings ~f:(fun pvb -> pvb.pvb_pat == pat) + in + Option.is_some pvb.pvb_constraint + | _ -> false ) | _ -> false let marked_parenzed_inner_nested_match = @@ -2093,8 +2127,8 @@ end = struct | ( Str { pstr_desc= Pstr_value - { lbs_rec= Nonrecursive - ; lbs_bindings= [{lb_pattern= {ppat_desc= Ppat_any; _}; _}] + { pvbs_rec= Nonrecursive + ; pvbs_bindings= [{pvb_pat= {ppat_desc= Ppat_any; _}; _}] ; _ } ; _ } , _ ) -> diff --git a/lib/Ast.mli b/lib/Ast.mli index f261826ede..2c81d469ae 100644 --- a/lib/Ast.mli +++ b/lib/Ast.mli @@ -110,7 +110,7 @@ type t = | Cty of class_type | Pat of pattern | Exp of expression - | Lb of let_binding + | Lb of value_binding | Mb of module_binding | Md of module_declaration | Cl of class_expr diff --git a/lib/Fmt_ast.ml b/lib/Fmt_ast.ml index 145e524d25..ac7c5a610a 100644 --- a/lib/Fmt_ast.ml +++ b/lib/Fmt_ast.ml @@ -2234,12 +2234,12 @@ and fmt_expression c ?(box = true) ?pro ?epi ?eol ?parens ?(indent_wrap = 0) $ fmt_atrs ) | Pexp_let (lbs, body) -> let bindings = - Sugar.Let_binding.of_let_bindings c.cmts ~ctx lbs.lbs_bindings + Sugar.Let_binding.of_let_bindings c.cmts ~ctx lbs.pvbs_bindings in let fmt_expr = fmt_expression c (sub_exp ~ctx body) in - let ext = lbs.lbs_extension in + let ext = lbs.pvbs_extension in fmt_let_bindings c ~ctx ?ext ~parens ~fmt_atrs ~fmt_expr ~has_attr - lbs.lbs_rec bindings body + lbs.pvbs_rec bindings body | Pexp_letop {let_; ands; body} -> let bd = Sugar.Let_binding.of_binding_ops c.cmts ~ctx (let_ :: ands) in let fmt_expr = fmt_expression c (sub_exp ~ctx body) in @@ -2276,7 +2276,7 @@ and fmt_expression c ?(box = true) ?pro ?epi ?eol ?parens ?(indent_wrap = 0) in let can_sparse = match xbody.ast.pmod_desc with - | Pmod_apply _ | Pmod_gen_apply _ -> true + | Pmod_apply _ | Pmod_apply_unit _ -> true | _ -> false in hvbox 0 @@ -2866,11 +2866,11 @@ and fmt_class_expr c ({ast= exp; ctx= ctx0} as xexp) = | _ -> c.conf.fmt_opts.indent_after_in.v in let bindings = - Sugar.Let_binding.of_let_bindings c.cmts ~ctx lbs.lbs_bindings + Sugar.Let_binding.of_let_bindings c.cmts ~ctx lbs.pvbs_bindings in let fmt_expr = fmt_class_expr c (sub_cl ~ctx body) in let has_attr = not (List.is_empty pcl_attributes) in - fmt_let c ctx ~ext:None ~rec_flag:lbs.lbs_rec ~bindings ~parens + fmt_let c ctx ~ext:None ~rec_flag:lbs.pvbs_rec ~bindings ~parens ~has_attr ~fmt_atrs ~fmt_expr ~body_loc:body.pcl_loc ~indent_after_in | Pcl_constraint (e, t) -> hvbox 2 @@ -4005,7 +4005,7 @@ and fmt_module_expr ?(dock_struct = true) c ({ast= m; _} as xmod) = @@ fun c -> let parens = parenze_mod xmod in match pmod_desc with - | Pmod_gen_apply (me, loc) -> + | Pmod_apply_unit (me, loc) -> let arg = Cmts.fmt c loc @@ hvbox 0 @@ wrap "(" ")" @@ Cmts.fmt_within c loc in @@ -4207,8 +4207,9 @@ and fmt_structure_item c ~last:last_item ?ext ~semisemi sub_mb | Pstr_type (rec_flag, decls) -> fmt_type c ?ext rec_flag decls ctx | Pstr_typext te -> fmt_type_extension ?ext c ctx te - | Pstr_value {lbs_rec= rec_flag; lbs_bindings= bindings; lbs_extension} -> - let update_config c i = update_config ~quiet:true c i.lb_attributes in + | Pstr_value {pvbs_rec= rec_flag; pvbs_bindings= bindings; pvbs_extension} + -> + let update_config c i = update_config ~quiet:true c i.pvb_attributes in let ast x = Lb x in let fmt_item c ctx ~prev ~next b = let first = Option.is_none prev in @@ -4224,7 +4225,7 @@ and fmt_structure_item c ~last:last_item ?ext ~semisemi (fits_breaks "" ~hint:(1000, 0) ";;") in let rec_flag = first && Asttypes.is_recursive rec_flag in - let ext = if first then lbs_extension else None in + let ext = if first then pvbs_extension else None in fmt_value_binding c ~rec_flag ?ext ctx ?epi b in fmt_item_list c ctx update_config ast fmt_item bindings @@ -4305,6 +4306,11 @@ and fmt_value_binding c ~rec_flag ?ext ?in_ ?epi ctx | `Other xtyp -> fmt_type_cstr c xtyp | `None -> noop in + let cstr_indent = + match lb_typ with + | `Other {ast= {ptyp_desc= Ptyp_poly _; _}; _} -> 6 + | _ -> 4 + in let indent = match lb_exp.ast.pexp_desc with | Pexp_function _ -> @@ -4346,7 +4352,7 @@ and fmt_value_binding c ~rec_flag ?ext ?in_ ?epi ctx ( hvbox_if toplevel 0 ( hvbox_if toplevel indent ( hovbox 2 - ( hovbox 4 + ( hovbox cstr_indent ( box_fun_decl_args c 4 ( hovbox 4 ( fmt_str_loc c lb_op diff --git a/lib/Sugar.ml b/lib/Sugar.ml index 13c2825daf..7e39c8d8b9 100644 --- a/lib/Sugar.ml +++ b/lib/Sugar.ml @@ -226,6 +226,48 @@ module Let_binding = struct ; lb_attrs: attribute list ; lb_loc: Location.t } + let split_annot cmts xargs ({ast= body; _} as xbody) = + let ctx = Exp body in + match body.pexp_desc with + | Pexp_constraint (exp, typ) + when Source.type_constraint_is_first typ exp.pexp_loc -> + Cmts.relocate cmts ~src:body.pexp_loc ~before:exp.pexp_loc + ~after:exp.pexp_loc ; + let typ_ctx = ctx in + let exp_ctx = + (* The type constraint is moved to the pattern, so we need to + replace the context from [Pexp_constraint] to [Pexp_fun]. This + won't be necessary once the normalization is moved to + [Extended_ast]. *) + let pat = Ast_helper.Pat.any () in + Exp (Ast_helper.Exp.fun_ Nolabel None pat exp) + in + (xargs, `Other (sub_typ ~ctx:typ_ctx typ), sub_exp ~ctx:exp_ctx exp) + (* The type constraint is always printed before the declaration for + functions, for other value bindings we preserve its position. *) + | Pexp_constraint (exp, typ) when not (List.is_empty xargs) -> + Cmts.relocate cmts ~src:body.pexp_loc ~before:exp.pexp_loc + ~after:exp.pexp_loc ; + (xargs, `Other (sub_typ ~ctx typ), sub_exp ~ctx exp) + | Pexp_coerce (exp, typ1, typ2) + when Source.type_constraint_is_first typ2 exp.pexp_loc -> + Cmts.relocate cmts ~src:body.pexp_loc ~before:exp.pexp_loc + ~after:exp.pexp_loc ; + let typ1 = Option.map typ1 ~f:(sub_typ ~ctx) in + (xargs, `Coerce (typ1, sub_typ ~ctx typ2), sub_exp ~ctx exp) + | _ -> (xargs, `None, xbody) + + let split_fun_args cmts xpat xbody = + let xargs, xbody = + match xpat.ast with + | {ppat_desc= Ppat_var _; ppat_attributes= []; _} -> + fun_ cmts ~will_keep_first_ast_node:false xbody + | _ -> ([], xbody) + in + match (xbody.ast.pexp_desc, xpat.ast.ppat_desc) with + | Pexp_constraint _, Ppat_constraint _ -> (xargs, `None, xbody) + | _ -> split_annot cmts xargs xbody + let type_cstr cmts ~ctx lb_pat lb_exp = let ({ast= pat; _} as xpat) = match (lb_pat.ppat_desc, lb_exp.pexp_desc) with @@ -257,69 +299,49 @@ module Let_binding = struct match polynewtype cmts pat body with | Some (xpat, pvars, xtyp, xbody) -> (xpat, [], `Polynewtype (pvars, xtyp), xbody) - | None -> ( + | None -> let xpat = match xpat.ast.ppat_desc with | Ppat_constraint (p, {ptyp_desc= Ptyp_poly ([], _); _}) -> sub_pat ~ctx:xpat.ctx p | _ -> xpat in - let xargs, ({ast= body; _} as xbody) = - match pat with - | {ppat_desc= Ppat_var _; ppat_attributes= []; _} -> - fun_ cmts ~will_keep_first_ast_node:false xbody - | _ -> ([], xbody) - in - let ctx = Exp body in - match (body.pexp_desc, pat.ppat_desc) with - | Pexp_constraint _, Ppat_constraint _ -> - (xpat, xargs, `None, xbody) - | Pexp_constraint (exp, typ), _ - when Source.type_constraint_is_first typ exp.pexp_loc -> - Cmts.relocate cmts ~src:body.pexp_loc ~before:exp.pexp_loc - ~after:exp.pexp_loc ; - let typ_ctx = Exp xbody.ast in - let exp_ctx = - (* The type constraint is moved to the pattern, so we need to - replace the context from [Pexp_constraint] to [Pexp_fun]. - This won't be necessary once the normalization is moved to - [Extended_ast]. *) - let pat = Ast_helper.Pat.any () in - Exp (Ast_helper.Exp.fun_ Nolabel None pat exp) - in - ( xpat - , xargs - , `Other (sub_typ ~ctx:typ_ctx typ) - , sub_exp ~ctx:exp_ctx exp ) - (* The type constraint is always printed before the declaration for - functions, for other value bindings we preserve its position. *) - | Pexp_constraint (exp, typ), _ when not (List.is_empty xargs) -> - Cmts.relocate cmts ~src:body.pexp_loc ~before:exp.pexp_loc - ~after:exp.pexp_loc ; - (xpat, xargs, `Other (sub_typ ~ctx typ), sub_exp ~ctx exp) - | Pexp_coerce (exp, typ1, typ2), _ - when Source.type_constraint_is_first typ2 exp.pexp_loc -> - Cmts.relocate cmts ~src:body.pexp_loc ~before:exp.pexp_loc - ~after:exp.pexp_loc ; - let typ1 = Option.map typ1 ~f:(sub_typ ~ctx) in - ( xpat - , xargs - , `Coerce (typ1, sub_typ ~ctx typ2) - , sub_exp ~ctx exp ) - | _ -> (xpat, xargs, `None, xbody) ) + let xargs, typ, xbody = split_fun_args cmts xpat xbody in + (xpat, xargs, typ, xbody) + + let typ_of_pvb_constraint ~ctx = function + | Some (Pvc_constraint {locally_abstract_univars= []; typ}) -> + `Other (sub_typ ~ctx typ) + | Some (Pvc_constraint {locally_abstract_univars; typ}) -> + `Polynewtype (locally_abstract_univars, sub_typ ~ctx typ) + | Some (Pvc_coercion {ground; coercion}) -> + `Coerce (Option.map ground ~f:(sub_typ ~ctx), sub_typ ~ctx coercion) + | None -> `None + + let should_desugar_args pat typ = + match (pat.ast, typ) with + | {ppat_desc= Ppat_var _; ppat_attributes= []; _}, `None -> true + | _ -> false - let of_let_binding cmts ~ctx ~first lb = - let lb_pat, lb_args, lb_typ, lb_exp = - type_cstr cmts ~ctx lb.lb_pattern lb.lb_expression + let of_let_binding cmts ~ctx ~first + {pvb_pat; pvb_expr; pvb_constraint; pvb_is_pun; pvb_attributes; pvb_loc} + = + let lb_exp = sub_exp ~ctx pvb_expr + and lb_pat = sub_pat ~ctx pvb_pat + and lb_typ = typ_of_pvb_constraint ~ctx pvb_constraint in + let lb_args, lb_typ, lb_exp = + if should_desugar_args lb_pat lb_typ then + split_fun_args cmts lb_pat lb_exp + else ([], lb_typ, lb_exp) in { lb_op= Location.{txt= (if first then "let" else "and"); loc= none} ; lb_pat ; lb_args ; lb_typ ; lb_exp - ; lb_pun= false - ; lb_attrs= lb.lb_attributes - ; lb_loc= lb.lb_loc } + ; lb_pun= pvb_is_pun + ; lb_attrs= pvb_attributes + ; lb_loc= pvb_loc } let of_let_bindings cmts ~ctx = List.mapi ~f:(fun i -> of_let_binding cmts ~ctx ~first:(i = 0)) diff --git a/lib/Sugar.mli b/lib/Sugar.mli index 75f15c40c0..43eebe2013 100644 --- a/lib/Sugar.mli +++ b/lib/Sugar.mli @@ -73,9 +73,10 @@ module Let_binding : sig ; lb_attrs: attribute list ; lb_loc: Location.t } - val of_let_binding : Cmts.t -> ctx:Ast.t -> first:bool -> let_binding -> t + val of_let_binding : + Cmts.t -> ctx:Ast.t -> first:bool -> value_binding -> t - val of_let_bindings : Cmts.t -> ctx:Ast.t -> let_binding list -> t list + val of_let_bindings : Cmts.t -> ctx:Ast.t -> value_binding list -> t list val of_binding_ops : Cmts.t -> ctx:Ast.t -> binding_op list -> t list end diff --git a/test/passing/tests/js_source.ml.ocp b/test/passing/tests/js_source.ml.ocp index 281aa3bb3e..b8711f80bc 100644 --- a/test/passing/tests/js_source.ml.ocp +++ b/test/passing/tests/js_source.ml.ocp @@ -1,6 +1,6 @@ [@@@foo] -let ((x [@foo]) : (unit[@foo])) = (() [@foo]) [@@foo] +let (x [@foo]) : (unit[@foo]) = (() [@foo]) [@@foo] type t = Foo of (t[@foo]) [@foo] [@@foo] @@ -36,27 +36,27 @@ type var = let x = 1 in x] -let ([%foo 2 + 1] : [%foo bar.baz]) = [%foo "foo"] +let [%foo 2 + 1] : [%foo bar.baz] = [%foo "foo"] [%%foo module M = [%bar]] -let ([%foo let () = ()] : [%foo type t = t]) = [%foo class c = object end] +let [%foo let () = ()] : [%foo type t = t] = [%foo class c = object end] [%%foo: 'a list] -let ([%foo: [ `Foo ]] : [%foo: t -> t]) = [%foo: < foo : t > ] +let [%foo: [ `Foo ]] : [%foo: t -> t] = [%foo: < foo : t > ] [%%foo? _] [%%foo? Some y when y > 0] -let ([%foo? Bar x | Baz x] : [%foo? #bar]) = [%foo? { x }] +let [%foo? Bar x | Baz x] : [%foo? #bar] = [%foo? { x }] [%%foo: module M : [%baz]] -let ([%foo: include S with type t = t] : - [%foo: - val x : t - val y : t]) +let [%foo: include S with type t = t] +: [%foo: + val x : t + val y : t] = [%foo: type t = t] ;; @@ -9417,7 +9417,7 @@ class ['a] c () = let f : type a'. a' = assert false let foo : type a' b'. a' -> b' = fun a -> assert false let foo : type t'. t' = fun (type t') : t' -> assert false -let foo : type t. t = assert false +let foo : 't. 't = fun (type t) : t -> assert false let foo : type a' b' c' t. a' -> b' -> c' -> t = fun a b c -> assert false let f x = diff --git a/test/passing/tests/js_source.ml.ref b/test/passing/tests/js_source.ml.ref index 91272d38d4..b23834a64f 100644 --- a/test/passing/tests/js_source.ml.ref +++ b/test/passing/tests/js_source.ml.ref @@ -1,6 +1,6 @@ [@@@foo] -let ((x [@foo]) : (unit[@foo])) = (() [@foo]) [@@foo] +let (x [@foo]) : (unit[@foo]) = (() [@foo]) [@@foo] type t = Foo of (t[@foo]) [@foo] [@@foo] @@ -36,27 +36,27 @@ type var = let x = 1 in x] -let ([%foo 2 + 1] : [%foo bar.baz]) = [%foo "foo"] +let [%foo 2 + 1] : [%foo bar.baz] = [%foo "foo"] [%%foo module M = [%bar]] -let ([%foo let () = ()] : [%foo type t = t]) = [%foo class c = object end] +let [%foo let () = ()] : [%foo type t = t] = [%foo class c = object end] [%%foo: 'a list] -let ([%foo: [ `Foo ]] : [%foo: t -> t]) = [%foo: < foo : t > ] +let [%foo: [ `Foo ]] : [%foo: t -> t] = [%foo: < foo : t > ] [%%foo? _] [%%foo? Some y when y > 0] -let ([%foo? Bar x | Baz x] : [%foo? #bar]) = [%foo? { x }] +let [%foo? Bar x | Baz x] : [%foo? #bar] = [%foo? { x }] [%%foo: module M : [%baz]] -let ([%foo: include S with type t = t] : - [%foo: - val x : t - val y : t]) +let [%foo: include S with type t = t] + : [%foo: + val x : t + val y : t] = [%foo: type t = t] ;; @@ -9417,7 +9417,7 @@ class ['a] c () = let f : type a'. a' = assert false let foo : type a' b'. a' -> b' = fun a -> assert false let foo : type t'. t' = fun (type t') : t' -> assert false -let foo : type t. t = assert false +let foo : 't. 't = fun (type t) : t -> assert false let foo : type a' b' c' t. a' -> b' -> c' -> t = fun a b c -> assert false let f x = diff --git a/test/passing/tests/let_binding-in_indent.ml.ref b/test/passing/tests/let_binding-in_indent.ml.ref index 9d8a1b5bd6..496d0aef81 100644 --- a/test/passing/tests/let_binding-in_indent.ml.ref +++ b/test/passing/tests/let_binding-in_indent.ml.ref @@ -13,7 +13,7 @@ let _ = let (x : int) = x in let x : int = x in let (_ : int) = x in - let (_ : int) = x in + let _ : int = x in () let%ext (_ : int) = x1 @@ -115,11 +115,11 @@ let _ = let (x : int) = x in let x : int = x in let (_ : int) = x in - let (_ : int) = x in + let _ : int = x in let%ext (x : int) = x in let%ext x : int = x in let%ext (_ : int) = x in - let%ext (_ : int) = x in + let%ext _ : int = x in () let fooo = fooooooooooo [@@foo] @@ -240,3 +240,24 @@ module A = struct match (l, r) with A, B -> "f A B" ;; end + +let (A (a, _, b) | B (b, a)) = A (1, 2, 3) + +let copy from ~into : unit = + let ({ pulse_captured_vars_length_contradictions + ; pulse_summaries_count + ; topl_reachable_calls + ; timeouts + ; timings } [@warning "+9"] ) = + () + in + () +;; + +let {x; y} : foo = bar + +let ({x; y} : foo) = bar + +let a, b = (raise Exit : int * int) + +let a, b = (raise Exit : int * int) diff --git a/test/passing/tests/let_binding-indent.ml.ref b/test/passing/tests/let_binding-indent.ml.ref index 577469e2ae..5e07912e98 100644 --- a/test/passing/tests/let_binding-indent.ml.ref +++ b/test/passing/tests/let_binding-indent.ml.ref @@ -13,7 +13,7 @@ let _ = let (x : int) = x in let x : int = x in let (_ : int) = x in - let (_ : int) = x in + let _ : int = x in () let%ext (_ : int) = x1 @@ -115,11 +115,11 @@ let _ = let (x : int) = x in let x : int = x in let (_ : int) = x in - let (_ : int) = x in + let _ : int = x in let%ext (x : int) = x in let%ext x : int = x in let%ext (_ : int) = x in - let%ext (_ : int) = x in + let%ext _ : int = x in () let fooo = fooooooooooo [@@foo] @@ -240,3 +240,24 @@ module A = struct match (l, r) with A, B -> "f A B" ;; end + +let (A (a, _, b) | B (b, a)) = A (1, 2, 3) + +let copy from ~into : unit = + let ({ pulse_captured_vars_length_contradictions + ; pulse_summaries_count + ; topl_reachable_calls + ; timeouts + ; timings } [@warning "+9"] ) = + () + in + () +;; + +let {x; y} : foo = bar + +let ({x; y} : foo) = bar + +let a, b = (raise Exit : int * int) + +let a, b = (raise Exit : int * int) diff --git a/test/passing/tests/let_binding.ml b/test/passing/tests/let_binding.ml index e21a79764f..d01ee58177 100644 --- a/test/passing/tests/let_binding.ml +++ b/test/passing/tests/let_binding.ml @@ -231,3 +231,21 @@ module A = struct match (l, r) with A, B -> "f A B" ;; end + +let (A (a, _, b) | B (b, a)) = A (1, 2, 3) + +let copy from ~into : unit = + let ({ + pulse_captured_vars_length_contradictions; + pulse_summaries_count; + topl_reachable_calls; + timeouts; + timings; + } [@warning "+9"]) = () in + () + +let { x; y } : foo = bar +let ({ x; y } : foo) = bar + +let a, b = (raise Exit : int * int) +let (a, b) = (raise Exit : int * int) diff --git a/test/passing/tests/let_binding.ml.ref b/test/passing/tests/let_binding.ml.ref index b45a996b9a..1920f73453 100644 --- a/test/passing/tests/let_binding.ml.ref +++ b/test/passing/tests/let_binding.ml.ref @@ -13,7 +13,7 @@ let _ = let (x : int) = x in let x : int = x in let (_ : int) = x in - let (_ : int) = x in + let _ : int = x in () let%ext (_ : int) = x1 @@ -115,11 +115,11 @@ let _ = let (x : int) = x in let x : int = x in let (_ : int) = x in - let (_ : int) = x in + let _ : int = x in let%ext (x : int) = x in let%ext x : int = x in let%ext (_ : int) = x in - let%ext (_ : int) = x in + let%ext _ : int = x in () let fooo = fooooooooooo [@@foo] @@ -240,3 +240,24 @@ module A = struct match (l, r) with A, B -> "f A B" ;; end + +let (A (a, _, b) | B (b, a)) = A (1, 2, 3) + +let copy from ~into : unit = + let ({ pulse_captured_vars_length_contradictions + ; pulse_summaries_count + ; topl_reachable_calls + ; timeouts + ; timings } [@warning "+9"] ) = + () + in + () +;; + +let {x; y} : foo = bar + +let ({x; y} : foo) = bar + +let a, b = (raise Exit : int * int) + +let a, b = (raise Exit : int * int) diff --git a/test/passing/tests/monadic_binding.ml b/test/passing/tests/monadic_binding.ml index 6683a155b2..dd28d238e4 100644 --- a/test/passing/tests/monadic_binding.ml +++ b/test/passing/tests/monadic_binding.ml @@ -27,3 +27,9 @@ let _ = ( let+ ) [@attr] let _ = f (( let+ ) [@attr]) ;; ( let+ ) [@attr] + +let _ = + let* (args, _) : bar = () in + let* (arg : bar) = () in + let* (_ : foo) = () in + () diff --git a/test/passing/tests/polytypes-janestreet.ml.ref b/test/passing/tests/polytypes-janestreet.ml.ref index 0787402439..963ec381b0 100644 --- a/test/passing/tests/polytypes-janestreet.ml.ref +++ b/test/passing/tests/polytypes-janestreet.ml.ref @@ -1,26 +1,26 @@ let t1 : 'a 'b. 'a t -> b t = () -let t2 : - 'a 'b. - 'a t________________________________ -> 'b t_______________________________________ +let t2 + : 'a 'b. + 'a t________________________________ -> 'b t_______________________________________ = () ;; -let t3 : - 'long 'sequence 'of_ 'universally 'quantified 'type_ 'variables 'that 'must 'wrap. - 'a t_________________________________________________ - -> 'b t______________________________________________________________ - -> 'c t______________________________________________________________ +let t3 + : 'long 'sequence 'of_ 'universally 'quantified 'type_ 'variables 'that 'must 'wrap. + 'a t_________________________________________________ + -> 'b t______________________________________________________________ + -> 'c t______________________________________________________________ = () ;; -let t4 : - 'long 'sequence 'of_ 'universally 'quantified 'type_ 'variables 'that 'must 'wrap. - 'a t_________________________________________________ - * 'b t______________________________________________________________ - * 'c t______________________________________________________________ +let t4 + : 'long 'sequence 'of_ 'universally 'quantified 'type_ 'variables 'that 'must 'wrap. + 'a t_________________________________________________ + * 'b t______________________________________________________________ + * 'c t______________________________________________________________ = () ;; diff --git a/test/passing/tests/source.ml.ref b/test/passing/tests/source.ml.ref index 947cccb6f7..da38d06db2 100644 --- a/test/passing/tests/source.ml.ref +++ b/test/passing/tests/source.ml.ref @@ -1,6 +1,6 @@ [@@@foo] -let ((x [@foo]) : (unit[@foo])) = (() [@foo]) [@@foo] +let (x [@foo]) : (unit[@foo]) = (() [@foo]) [@@foo] type t = Foo of (t[@foo]) [@foo] [@@foo] @@ -39,29 +39,29 @@ type var = [`Foo (** foo *) | `Bar of int * string (** bar *)] let x = 1 in x] -let ([%foo 2 + 1] : [%foo bar.baz]) = [%foo "foo"] +let [%foo 2 + 1] : [%foo bar.baz] = [%foo "foo"] [%%foo module M = [%bar]] -let ([%foo let () = ()] : [%foo type t = t]) = [%foo class c = object end] +let [%foo let () = ()] : [%foo type t = t] = [%foo class c = object end] [%%foo: 'a list] -let ([%foo: [`Foo]] : [%foo: t -> t]) = [%foo: < foo: t > ] +let [%foo: [`Foo]] : [%foo: t -> t] = [%foo: < foo: t > ] [%%foo? _] [%%foo? Some y when y > 0] -let ([%foo? Bar x | Baz x] : [%foo? #bar]) = [%foo? {x}] +let [%foo? Bar x | Baz x] : [%foo? #bar] = [%foo? {x}] [%%foo: module M : [%baz]] -let ([%foo: include S with type t = t] : - [%foo: - val x : t +let [%foo: include S with type t = t] : + [%foo: + val x : t - val y : t] ) = + val y : t] = [%foo: type t = t] let int_with_custom_modifier = @@ -9029,7 +9029,7 @@ let foo : type a' b'. a' -> b' = fun a -> assert false let foo : type t'. t' = fun (type t') : t' -> assert false -let foo : type t. t = assert false +let foo : 't. 't = fun (type t) : t -> assert false let foo : type a' b' c' t. a' -> b' -> c' -> t = fun a b c -> assert false diff --git a/vendor/parser-extended/ast_helper.ml b/vendor/parser-extended/ast_helper.ml index 4efc07c26c..1af7e480af 100644 --- a/vendor/parser-extended/ast_helper.ml +++ b/vendor/parser-extended/ast_helper.ml @@ -209,7 +209,7 @@ let mk ?(loc = !default_loc) ?(attrs = []) d = let apply ?loc ?attrs m1 m2 = mk ?loc ?attrs (Pmod_apply (m1, m2)) let constraint_ ?loc ?attrs m mty = mk ?loc ?attrs (Pmod_constraint (m, mty)) let unpack ?loc ?attrs a b c = mk ?loc ?attrs (Pmod_unpack (a, b, c)) - let gen_apply ?loc ?attrs a b = mk ?loc ?attrs (Pmod_gen_apply (a, b)) + let apply_unit ?loc ?attrs a b = mk ?loc ?attrs (Pmod_apply_unit (a, b)) let extension ?loc ?attrs a = mk ?loc ?attrs (Pmod_extension a) let hole ?loc ?attrs () = mk ?loc ?attrs Pmod_hole end @@ -437,6 +437,20 @@ module Incl = struct end +module Vb = struct + let mk ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) + ?(text = []) ?value_constraint ~is_pun pat expr = + { + pvb_pat = pat; + pvb_expr = expr; + pvb_constraint=value_constraint; + pvb_is_pun = is_pun; + pvb_attributes = + add_text_attrs text (add_docs_attrs docs attrs); + pvb_loc = loc; + } +end + module Ci = struct let mk ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) ?(text = []) diff --git a/vendor/parser-extended/ast_helper.mli b/vendor/parser-extended/ast_helper.mli index 2bc2c03322..fd28c99b11 100644 --- a/vendor/parser-extended/ast_helper.mli +++ b/vendor/parser-extended/ast_helper.mli @@ -128,7 +128,7 @@ module Exp: val ident: ?loc:loc -> ?attrs:attrs -> lid -> expression val constant: ?loc:loc -> ?attrs:attrs -> constant -> expression - val let_: ?loc:loc -> ?attrs:attrs -> let_bindings -> expression -> expression + val let_: ?loc:loc -> ?attrs:attrs -> value_bindings -> expression -> expression val fun_: ?loc:loc -> ?attrs:attrs -> arg_label -> expression option -> pattern -> expression -> expression val function_: ?loc:loc -> ?attrs:attrs -> case list -> expression @@ -284,7 +284,7 @@ module Mod: module_expr val unpack: ?loc:loc -> ?attrs:attrs -> expression -> package_type option -> package_type option -> module_expr - val gen_apply: ?loc:loc -> ?attrs:attrs -> module_expr -> loc -> module_expr + val apply_unit: ?loc:loc -> ?attrs:attrs -> module_expr -> loc -> module_expr val extension: ?loc:loc -> ?attrs:attrs -> extension -> module_expr val hole: ?loc:loc -> ?attrs:attrs -> unit -> module_expr end @@ -319,7 +319,7 @@ module Str: val mk: ?loc:loc -> structure_item_desc -> structure_item val eval: ?loc:loc -> ?attrs:attributes -> expression -> structure_item - val value: ?loc:loc -> let_bindings -> structure_item + val value: ?loc:loc -> value_bindings -> structure_item val primitive: ?loc:loc -> value_description -> structure_item val type_: ?loc:loc -> rec_flag -> type_declaration list -> structure_item val type_extension: ?loc:loc -> type_extension -> structure_item @@ -377,6 +377,14 @@ module Incl: val mk: ?loc: loc -> ?attrs:attrs -> ?docs:docs -> 'a -> 'a include_infos end +(** Value bindings *) +module Vb: + sig + val mk: ?loc: loc -> ?attrs:attrs -> ?docs:docs -> ?text:text -> + ?value_constraint:value_constraint -> is_pun:bool -> pattern -> + expression -> value_binding + end + (** {1 Class language} *) @@ -426,7 +434,7 @@ module Cl: pattern -> class_expr -> class_expr val apply: ?loc:loc -> ?attrs:attrs -> class_expr -> (arg_label * expression) list -> class_expr - val let_: ?loc:loc -> ?attrs:attrs -> let_bindings -> class_expr -> class_expr + val let_: ?loc:loc -> ?attrs:attrs -> value_bindings -> class_expr -> class_expr val constraint_: ?loc:loc -> ?attrs:attrs -> class_expr -> class_type -> class_expr val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_expr diff --git a/vendor/parser-extended/ast_mapper.ml b/vendor/parser-extended/ast_mapper.ml index 639b0f3b4f..471ddf03ca 100644 --- a/vendor/parser-extended/ast_mapper.ml +++ b/vendor/parser-extended/ast_mapper.ml @@ -53,8 +53,6 @@ type mapper = { include_declaration: mapper -> include_declaration -> include_declaration; include_description: mapper -> include_description -> include_description; label_declaration: mapper -> label_declaration -> label_declaration; - let_binding: mapper -> let_binding -> let_binding; - let_bindings: mapper -> let_bindings -> let_bindings; location: mapper -> Location.t -> Location.t; module_binding: mapper -> module_binding -> module_binding; module_declaration: mapper -> module_declaration -> module_declaration; @@ -76,6 +74,8 @@ type mapper = { type_extension: mapper -> type_extension -> type_extension; type_exception: mapper -> type_exception -> type_exception; type_kind: mapper -> type_kind -> type_kind; + value_binding: mapper -> value_binding -> value_binding; + value_bindings: mapper -> value_bindings -> value_bindings; value_description: mapper -> value_description -> value_description; with_constraint: mapper -> with_constraint -> with_constraint; directive_argument: mapper -> directive_argument -> directive_argument; @@ -424,6 +424,8 @@ module M = struct (sub.module_expr sub body) | Pmod_apply (m1, m2) -> apply ~loc ~attrs (sub.module_expr sub m1) (sub.module_expr sub m2) + | Pmod_apply_unit (me, lc) -> + apply_unit ~loc ~attrs (sub.module_expr sub me) (sub.location sub lc) | Pmod_constraint (m, mty) -> constraint_ ~loc ~attrs (sub.module_expr sub m) (sub.module_type sub mty) @@ -432,8 +434,6 @@ module M = struct (sub.expr sub e) (map_opt (map_package_type sub) ty1) (map_opt (map_package_type sub) ty2) - | Pmod_gen_apply (me, lc) -> - gen_apply ~loc ~attrs (sub.module_expr sub me) (sub.location sub lc) | Pmod_extension x -> extension ~loc ~attrs (sub.extension sub x) | Pmod_hole -> hole ~loc ~attrs () @@ -444,7 +444,7 @@ module M = struct | Pstr_eval (x, attrs) -> let attrs = sub.attributes sub attrs in eval ~loc ~attrs (sub.expr sub x) - | Pstr_value lbs -> value ~loc (sub.let_bindings sub lbs) + | Pstr_value lbs -> value ~loc (sub.value_bindings sub lbs) | Pstr_primitive vd -> primitive ~loc (sub.value_description sub vd) | Pstr_type (rf, l) -> type_ ~loc rf (List.map (sub.type_declaration sub) l) | Pstr_typext te -> type_extension ~loc (sub.type_extension sub te) @@ -480,7 +480,7 @@ module E = struct | Pexp_ident x -> ident ~loc ~attrs (map_loc sub x) | Pexp_constant x -> constant ~loc ~attrs (sub.constant sub x) | Pexp_let (lbs, e) -> - let_ ~loc ~attrs (sub.let_bindings sub lbs) + let_ ~loc ~attrs (sub.value_bindings sub lbs) (sub.expr sub e) | Pexp_fun (lab, def, p, e) -> fun_ ~loc ~attrs @@ -597,18 +597,11 @@ module E = struct end -module LB = struct - let map_let_binding sub { lb_pattern; lb_expression; lb_is_pun; lb_attributes; lb_loc } = - let lb_pattern = sub.pat sub lb_pattern in - let lb_expression = sub.expr sub lb_expression in - let lb_attributes = sub.attributes sub lb_attributes in - let lb_loc = sub.location sub lb_loc in - { lb_pattern; lb_expression; lb_is_pun; lb_attributes; lb_loc } - - let map_let_bindings sub { lbs_bindings; lbs_rec; lbs_extension } = - let lbs_bindings = List.map (sub.let_binding sub) lbs_bindings in - let lbs_extension = map_opt (map_loc sub) lbs_extension in - { lbs_bindings; lbs_rec; lbs_extension } +module PVB = struct + let map_value_bindings sub { pvbs_bindings; pvbs_rec; pvbs_extension } = + let pvbs_bindings = List.map (sub.value_binding sub) pvbs_bindings in + let pvbs_extension = map_opt (map_loc sub) pvbs_extension in + { pvbs_bindings; pvbs_rec; pvbs_extension } end module P = struct @@ -680,7 +673,7 @@ module CE = struct apply ~loc ~attrs (sub.class_expr sub ce) (List.map (map_tuple (sub.arg_label sub) (sub.expr sub)) l) | Pcl_let (lbs, ce) -> - let_ ~loc ~attrs (sub.let_bindings sub lbs) + let_ ~loc ~attrs (sub.value_bindings sub lbs) (sub.class_expr sub ce) | Pcl_constraint (ce, ct) -> constraint_ ~loc ~attrs (sub.class_expr sub ce) (sub.class_type sub ct) @@ -777,9 +770,6 @@ let default_mapper = expr = E.map; binding_op = E.map_binding_op; - let_binding = LB.map_let_binding; - let_bindings = LB.map_let_bindings; - module_declaration = (fun this {pmd_name; pmd_args; pmd_type; pmd_attributes; pmd_loc} -> Md.mk @@ -848,6 +838,30 @@ let default_mapper = ~attrs:(this.attributes this pincl_attributes) ); + value_binding = + (fun this {pvb_pat; pvb_expr; pvb_constraint; pvb_is_pun; pvb_attributes; pvb_loc} -> + let map_ct (ct:Parsetree.value_constraint) = match ct with + | Pvc_constraint {locally_abstract_univars=vars; typ} -> + Pvc_constraint + { locally_abstract_univars = List.map (map_loc this) vars; + typ = this.typ this typ + } + | Pvc_coercion { ground; coercion } -> + Pvc_coercion { + ground = Option.map (this.typ this) ground; + coercion = this.typ this coercion + } + in + Vb.mk + (this.pat this pvb_pat) + (this.expr this pvb_expr) + ?value_constraint:(Option.map map_ct pvb_constraint) + ~is_pun:pvb_is_pun + ~loc:(this.location this pvb_loc) + ~attrs:(this.attributes this pvb_attributes) + ); + value_bindings = PVB.map_value_bindings; + constructor_declaration = (fun this {pcd_name; pcd_vars; pcd_args; pcd_res; pcd_loc; pcd_attributes} -> diff --git a/vendor/parser-extended/ast_mapper.mli b/vendor/parser-extended/ast_mapper.mli index 6e28ddab93..e868f07164 100644 --- a/vendor/parser-extended/ast_mapper.mli +++ b/vendor/parser-extended/ast_mapper.mli @@ -82,8 +82,6 @@ type mapper = { include_declaration: mapper -> include_declaration -> include_declaration; include_description: mapper -> include_description -> include_description; label_declaration: mapper -> label_declaration -> label_declaration; - let_binding: mapper -> let_binding -> let_binding; - let_bindings: mapper -> let_bindings -> let_bindings; location: mapper -> Location.t -> Location.t; module_binding: mapper -> module_binding -> module_binding; module_declaration: mapper -> module_declaration -> module_declaration; @@ -105,6 +103,8 @@ type mapper = { type_extension: mapper -> type_extension -> type_extension; type_exception: mapper -> type_exception -> type_exception; type_kind: mapper -> type_kind -> type_kind; + value_binding: mapper -> value_binding -> value_binding; + value_bindings: mapper -> value_bindings -> value_bindings; value_description: mapper -> value_description -> value_description; with_constraint: mapper -> with_constraint -> with_constraint; directive_argument: mapper -> directive_argument -> directive_argument; diff --git a/vendor/parser-extended/parser.mly b/vendor/parser-extended/parser.mly index b86e5b45d5..a7a060cee8 100644 --- a/vendor/parser-extended/parser.mly +++ b/vendor/parser-extended/parser.mly @@ -428,14 +428,31 @@ let extra_rhs_core_type ct ~pos = let docs = rhs_info pos in { ct with ptyp_attributes = add_info_attrs docs ct.ptyp_attributes } -let mklb first ~loc (p, e, is_pun) attrs = - let docs = symbol_docs loc in - let text = if first then empty_text else symbol_text (fst loc) in +type let_binding = + { lb_pattern: pattern; + lb_expression: expression; + lb_constraint: value_constraint option; + lb_is_pun: bool; + lb_attributes: attributes; + lb_docs: docs Lazy.t; + lb_text: text Lazy.t; + lb_loc: Location.t; } + +type let_bindings' = + { lbs_bindings: let_binding list; + lbs_rec: rec_flag; + lbs_extension: string Asttypes.loc option } + +let mklb first ~loc (p, e, typ, is_pun) attrs = { lb_pattern = p; lb_expression = e; + lb_constraint=typ; lb_is_pun = is_pun; - lb_attributes = add_text_attrs text (add_docs_attrs docs attrs); + lb_attributes = attrs; + lb_docs = symbol_docs_lazy loc; + lb_text = (if first then empty_text_lazy + else symbol_text_lazy (fst loc)); lb_loc = make_loc loc; } @@ -451,17 +468,29 @@ let mklbs ext rf lb = } in addlb lbs lb +let mk_let_bindings { lbs_bindings; lbs_rec; lbs_extension } = + let pvbs_bindings = + List.rev_map + (fun lb -> + Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes + ~docs:(Lazy.force lb.lb_docs) + ~text:(Lazy.force lb.lb_text) + ?value_constraint:lb.lb_constraint ~is_pun:lb.lb_is_pun + lb.lb_pattern lb.lb_expression) + lbs_bindings + in + { pvbs_bindings; pvbs_rec = lbs_rec; pvbs_extension = lbs_extension } + let val_of_let_bindings ~loc lbs = - let lbs = { lbs with lbs_bindings= List.rev lbs.lbs_bindings } in - mkstr ~loc (Pstr_value lbs) + mkstr ~loc (Pstr_value (mk_let_bindings lbs)) let expr_of_let_bindings ~loc lbs body = - let lbs = { lbs with lbs_bindings= List.rev lbs.lbs_bindings } in - mkexp ~loc (Pexp_let (lbs, body)) + mkexp_attrs ~loc (Pexp_let (mk_let_bindings lbs, body)) (None, []) let class_of_let_bindings ~loc lbs body = - let lbs = { lbs with lbs_bindings= List.rev lbs.lbs_bindings } in - mkclass ~loc (Pcl_let (lbs, body)) + (* Our use of let_bindings(no_ext) guarantees the following: *) + assert (lbs.lbs_extension = None); + mkclass ~loc (Pcl_let (mk_let_bindings lbs, body)) (* Alternatively, we could keep the generic module type in the Parsetree and extract the package type during type-checking. In that case, @@ -1219,8 +1248,9 @@ module_expr: | (* In a functor application, the actual argument must be parenthesized. *) me1 = module_expr me2 = paren_module_expr { Pmod_apply(me1, me2) } - | me = module_expr LPAREN RPAREN - { Pmod_gen_apply (me, make_loc ($startpos($2), $endpos($3))) } + | (* Functor applied to unit. *) + me = module_expr LPAREN RPAREN + { Pmod_apply_unit (me, make_loc ($startpos($2), $endpos($3))) } | (* An extension. *) ex = extension { Pmod_extension ex } @@ -1622,6 +1652,22 @@ signature_item: } ; +(* Module arguments are attached to declarations +(* The body (right-hand side) of a module declaration. *) +module_declaration_body: + COLON mty = module_type + { mty } + | EQUAL error + { expecting $loc($1) ":" } + | mkmty( + arg_and_pos = functor_arg body = module_declaration_body + { let (_, arg) = arg_and_pos in + Pmty_functor(arg, body) } + ) + { $1 } +; +*) + (* A module alias declaration (in a signature). *) %inline module_alias: MODULE @@ -2436,42 +2482,39 @@ labeled_simple_expr: ; let_binding_body_no_punning: let_ident strict_binding - { ($1, $2) } + { ($1, $2, None) } | let_ident type_constraint EQUAL seq_expr { let v = $1 in (* PR#7344 *) let t = match $2 with - Some t, None -> t - | _, Some t -> t + Some t, None -> + Pvc_constraint { locally_abstract_univars = []; typ=t } + | ground, Some coercion -> Pvc_coercion { ground; coercion} | _ -> assert false in - let loc = Location.(t.ptyp_loc.loc_start, t.ptyp_loc.loc_end) in - let typ = ghtyp ~loc (Ptyp_poly([],t)) in - let patloc = ($startpos($1), $endpos($2)) in - (ghpat ~loc:patloc (Ppat_constraint(v, typ)), - mkexp_constraint ~loc:$sloc $4 $2) } + (v, $4, Some t) + } | let_ident COLON poly(core_type) EQUAL seq_expr - { let patloc = ($startpos($1), $endpos($3)) in - (ghpat ~loc:patloc - (Ppat_constraint($1, ghtyp ~loc:($loc($3)) $3)), - $5) } + { + let t = ghtyp ~loc:($loc($3)) $3 in + ($1, $5, Some (Pvc_constraint { locally_abstract_univars = []; typ=t })) + } | let_ident COLON TYPE lident_list DOT core_type EQUAL seq_expr - { let exp, poly = - wrap_type_annotation ~loc:$sloc $4 $6 $8 in - let loc = ($startpos($1), $endpos($6)) in - (ghpat ~loc (Ppat_constraint($1, poly)), exp) } + { let constraint' = + Pvc_constraint { locally_abstract_univars=$4; typ = $6} + in + ($1, $8, Some constraint') } | pattern_no_exn EQUAL seq_expr - { ($1, $3) } + { ($1, $3, None) } | simple_pattern_not_ident COLON core_type EQUAL seq_expr - { let loc = ($startpos($1), $endpos($3)) in - (ghpat ~loc (Ppat_constraint($1, $3)), $5) } + { ($1, $5, Some(Pvc_constraint { locally_abstract_univars=[]; typ=$3 })) } ; let_binding_body: | let_binding_body_no_punning - { let p,e = $1 in (p,e,false) } + { let p,e,c = $1 in (p,e,c,false) } /* BEGIN AVOID */ | val_ident %prec below_HASH - { (mkpatvar ~loc:$loc $1, mkexpvar ~loc:$loc $1, true) } + { (mkpatvar ~loc:$loc $1, mkexpvar ~loc:$loc $1, None, true) } (* The production that allows puns is marked so that [make list-parse-errors] does not attempt to exploit it. That would be problematic because it would then generate bindings such as [let x], which are rejected by the diff --git a/vendor/parser-extended/parsetree.mli b/vendor/parser-extended/parsetree.mli index 4ab29245c7..ff8818429d 100644 --- a/vendor/parser-extended/parsetree.mli +++ b/vendor/parser-extended/parsetree.mli @@ -307,7 +307,7 @@ and expression_desc = | Pexp_constant of constant (** Expressions constant such as [1], ['a'], ["true"], [1.0], [1l], [1L], [1n] *) - | Pexp_let of let_bindings * expression + | Pexp_let of value_bindings * expression (** [Pexp_let(flag, [(P1,E1) ; ... ; (Pn,En)], E)] represents: - [let P1 = E1 and ... and Pn = EN in E] when [flag] is {{!Asttypes.rec_flag.Nonrecursive}[Nonrecursive]}, @@ -773,7 +773,7 @@ and class_expr_desc = Invariant: [n > 0] *) - | Pcl_let of let_bindings * class_expr + | Pcl_let of value_bindings * class_expr (** [Pcl_let(rec, [(P1, E1); ... ; (Pn, En)], CE)] represents: - [let P1 = E1 and ... and Pn = EN in CE] when [rec] is {{!Asttypes.rec_flag.Nonrecursive}[Nonrecursive]}, @@ -1016,10 +1016,11 @@ and module_expr_desc = | Pmod_functor of functor_parameter loc list * module_expr (** [functor (X1 : MT1) ... (Xn : MTn) -> ME] *) | Pmod_apply of module_expr * module_expr (** [ME1(ME2)] *) + | Pmod_apply_unit of module_expr * Location.t + (** [ME1()]. The location argument correspond to the [()]. *) | Pmod_constraint of module_expr * module_type (** [(ME : MT)] *) | Pmod_unpack of expression * package_type option * package_type option (** [(val E : M1 :> M2)] *) - | Pmod_gen_apply of module_expr * Location.t (** [ME()] *) | Pmod_extension of extension (** [[%id]] *) | Pmod_hole (** [_] *) @@ -1033,7 +1034,7 @@ and structure_item = and structure_item_desc = | Pstr_eval of expression * attributes (** [E] *) - | Pstr_value of let_bindings + | Pstr_value of value_bindings (** [Pstr_value(rec, [(P1, E1 ; ... ; (Pn, En))])] represents: - [let P1 = E1 and ... and Pn = EN] when [rec] is {{!Asttypes.rec_flag.Nonrecursive}[Nonrecursive]}, @@ -1062,20 +1063,37 @@ and structure_item_desc = | Pstr_attribute of attribute (** [[\@\@\@id]] *) | Pstr_extension of extension * attributes (** [[%%id]] *) -and let_binding = - { - lb_pattern: pattern; - lb_expression: expression; - lb_is_pun: bool; - lb_attributes: attributes; - lb_loc: Location.t; - } +and value_constraint = + | Pvc_constraint of { + locally_abstract_univars:string loc list; + typ:core_type; + } + | Pvc_coercion of {ground:core_type option; coercion:core_type } + (** + - [Pvc_constraint { locally_abstract_univars=[]; typ}] + is a simple type constraint on a value binding: [ let x : typ] + - More generally, in [Pvc_constraint { locally_abstract_univars; typ}] + [locally_abstract_univars] is the list of locally abstract type + variables in [ let x: type a ... . typ ] + - [Pvc_coercion { ground=None; coercion }] represents [let x :> typ] + - [Pvc_coercion { ground=Some g; coercion }] represents [let x : g :> typ] + *) -and let_bindings = +and value_binding = + { + pvb_pat: pattern; + pvb_expr: expression; + pvb_constraint: value_constraint option; + pvb_is_pun: bool; + pvb_attributes: attributes; + pvb_loc: Location.t; + }(** [let pat : type_constraint = exp] *) + +and value_bindings = { - lbs_bindings: let_binding list; - lbs_rec: rec_flag; - lbs_extension: string loc option + pvbs_bindings: value_binding list; + pvbs_rec: rec_flag; + pvbs_extension: string loc option } and module_binding = diff --git a/vendor/parser-extended/printast.ml b/vendor/parser-extended/printast.ml index f9284a9c7d..1c07ba665b 100644 --- a/vendor/parser-extended/printast.ml +++ b/vendor/parser-extended/printast.ml @@ -339,8 +339,8 @@ and expression i ppf x = line i ppf "Pexp_constant\n"; fmt_constant i ppf c; | Pexp_let (l, e) -> - line i ppf "Pexp_let %a\n" fmt_rec_flag l.lbs_rec; - let_bindings i ppf l; + line i ppf "Pexp_let %a\n" fmt_rec_flag l.pvbs_rec; + value_bindings i ppf l; expression i ppf e; | Pexp_function l -> line i ppf "Pexp_function\n"; @@ -710,8 +710,8 @@ and class_expr i ppf x = class_expr i ppf ce; list i label_x_expression ppf l; | Pcl_let (lbs, ce) -> - line i ppf "Pcl_let %a\n" fmt_rec_flag lbs.lbs_rec; - let_bindings i ppf lbs; + line i ppf "Pcl_let %a\n" fmt_rec_flag lbs.pvbs_rec; + value_bindings i ppf lbs; class_expr i ppf ce; | Pcl_constraint (ce, ct) -> line i ppf "Pcl_constraint\n"; @@ -930,8 +930,8 @@ and module_expr i ppf x = expression i ppf e; option i package_type ppf ty1; option i package_type ppf ty2 - | Pmod_gen_apply (x, loc) -> - line i ppf "Pmod_gen_apply\n"; + | Pmod_apply_unit (x, loc) -> + line i ppf "Pmod_apply_unit\n"; module_expr i ppf x; line (i+1) ppf "() %a" fmt_location loc | Pmod_extension (s, arg) -> @@ -951,8 +951,8 @@ and structure_item i ppf x = attributes i ppf attrs; expression i ppf e; | Pstr_value l -> - line i ppf "Pstr_value %a\n" fmt_rec_flag l.lbs_rec; - let_bindings i ppf l + line i ppf "Pstr_value %a\n" fmt_rec_flag l.pvbs_rec; + value_bindings i ppf l | Pstr_primitive vd -> line i ppf "Pstr_primitive\n"; value_description i ppf vd; @@ -1052,6 +1052,27 @@ and case i ppf {pc_lhs; pc_guard; pc_rhs} = end; expression (i+1) ppf pc_rhs; +and value_binding i ppf x = + line i ppf " %a\n" fmt_location x.pvb_loc; + attributes (i+1) ppf x.pvb_attributes; + pattern (i+1) ppf x.pvb_pat; + Option.iter (value_constraint (i+1) ppf) x.pvb_constraint; + expression (i+1) ppf x.pvb_expr + +and value_constraint i ppf x = + let pp_sep ppf () = Format.fprintf ppf "@ "; in + let pp_newtypes = Format.pp_print_list fmt_string_loc ~pp_sep in + match x with + | Pvc_constraint { locally_abstract_univars = []; typ } -> + core_type i ppf typ + | Pvc_constraint { locally_abstract_univars=newtypes; typ} -> + line i ppf " %a.\n" pp_newtypes newtypes; + core_type i ppf typ + | Pvc_coercion { ground; coercion} -> + line i ppf "\n"; + option i core_type ppf ground; + core_type i ppf coercion; + and open_description i ppf x = line i ppf "open_description %a %a\n" fmt_override_flag x.popen_override fmt_location x.popen_loc; @@ -1077,14 +1098,8 @@ and include_declaration i ppf x = let i = i+1 in module_expr i ppf x.pincl_mod -and let_binding i ppf x = - line i ppf " %a\n" fmt_location x.lb_loc; - attributes (i+1) ppf x.lb_attributes; - pattern (i+1) ppf x.lb_pattern; - expression (i+1) ppf x.lb_expression - -and let_bindings i ppf x = - list i let_binding ppf x.lbs_bindings +and value_bindings i ppf x = + list i value_binding ppf x.pvbs_bindings and binding_op i ppf x = line i ppf " %a %a" @@ -1168,7 +1183,7 @@ let pattern ppf x = pattern 0 ppf x let type_declaration ppf x = type_declaration 0 ppf x -let let_binding ppf x = let_binding 0 ppf x +let value_binding ppf x = value_binding 0 ppf x let module_binding ppf x = module_binding 0 ppf x diff --git a/vendor/parser-extended/printast.mli b/vendor/parser-extended/printast.mli index 68160ed574..2f3fe19503 100644 --- a/vendor/parser-extended/printast.mli +++ b/vendor/parser-extended/printast.mli @@ -35,7 +35,7 @@ val core_type: formatter -> core_type -> unit val module_type: formatter -> module_type -> unit val pattern: formatter -> pattern -> unit val type_declaration: formatter -> type_declaration -> unit -val let_binding: formatter -> let_binding -> unit +val value_binding: formatter -> value_binding -> unit val module_binding: formatter -> module_binding -> unit val module_declaration: formatter -> module_declaration -> unit val class_expr: formatter -> class_expr -> unit diff --git a/vendor/parser-standard/ast_helper.ml b/vendor/parser-standard/ast_helper.ml index 1a3fedf602..ae65b50931 100644 --- a/vendor/parser-standard/ast_helper.ml +++ b/vendor/parser-standard/ast_helper.ml @@ -246,8 +246,8 @@ module Mty = struct end module Mod = struct -let mk ?(loc = !default_loc) ?(attrs = []) d = - {pmod_desc = d; pmod_loc = loc; pmod_attributes = attrs} + let mk ?(loc = !default_loc) ?(attrs = []) d = + {pmod_desc = d; pmod_loc = loc; pmod_attributes = attrs} let attr d a = {d with pmod_attributes = d.pmod_attributes @ [a]} let ident ?loc ?attrs x = mk ?loc ?attrs (Pmod_ident x) @@ -255,6 +255,7 @@ let mk ?(loc = !default_loc) ?(attrs = []) d = let functor_ ?loc ?attrs arg body = mk ?loc ?attrs (Pmod_functor (arg, body)) let apply ?loc ?attrs m1 m2 = mk ?loc ?attrs (Pmod_apply (m1, m2)) + let apply_unit ?loc ?attrs m1 = mk ?loc ?attrs (Pmod_apply_unit m1) let constraint_ ?loc ?attrs m mty = mk ?loc ?attrs (Pmod_constraint (m, mty)) let unpack ?loc ?attrs e = mk ?loc ?attrs (Pmod_unpack e) let extension ?loc ?attrs a = mk ?loc ?attrs (Pmod_extension a) @@ -484,10 +485,11 @@ end module Vb = struct let mk ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) - ?(text = []) pat expr = + ?(text = []) ?value_constraint pat expr = { pvb_pat = pat; pvb_expr = expr; + pvb_constraint=value_constraint; pvb_attributes = add_text_attrs text (add_docs_attrs docs attrs); pvb_loc = loc; diff --git a/vendor/parser-standard/ast_helper.mli b/vendor/parser-standard/ast_helper.mli index 422f0955a5..68e3396566 100644 --- a/vendor/parser-standard/ast_helper.mli +++ b/vendor/parser-standard/ast_helper.mli @@ -271,6 +271,7 @@ module Mod: functor_parameter -> module_expr -> module_expr val apply: ?loc:loc -> ?attrs:attrs -> module_expr -> module_expr -> module_expr + val apply_unit: ?loc:loc -> ?attrs:attrs -> module_expr -> module_expr val constraint_: ?loc:loc -> ?attrs:attrs -> module_expr -> module_type -> module_expr val unpack: ?loc:loc -> ?attrs:attrs -> expression -> module_expr @@ -370,7 +371,8 @@ module Incl: module Vb: sig val mk: ?loc: loc -> ?attrs:attrs -> ?docs:docs -> ?text:text -> - pattern -> expression -> value_binding + ?value_constraint:value_constraint -> pattern -> expression -> + value_binding end diff --git a/vendor/parser-standard/ast_mapper.ml b/vendor/parser-standard/ast_mapper.ml index 59503aa5ac..7b399f07b1 100644 --- a/vendor/parser-standard/ast_mapper.ml +++ b/vendor/parser-standard/ast_mapper.ml @@ -353,6 +353,8 @@ module M = struct (sub.module_expr sub body) | Pmod_apply (m1, m2) -> apply ~loc ~attrs (sub.module_expr sub m1) (sub.module_expr sub m2) + | Pmod_apply_unit m1 -> + apply_unit ~loc ~attrs (sub.module_expr sub m1) | Pmod_constraint (m, mty) -> constraint_ ~loc ~attrs (sub.module_expr sub m) (sub.module_type sub mty) @@ -696,10 +698,23 @@ let default_mapper = value_binding = - (fun this {pvb_pat; pvb_expr; pvb_attributes; pvb_loc} -> + (fun this {pvb_pat; pvb_expr; pvb_constraint; pvb_attributes; pvb_loc} -> + let map_ct (ct:Parsetree.value_constraint) = match ct with + | Pvc_constraint {locally_abstract_univars=vars; typ} -> + Pvc_constraint + { locally_abstract_univars = List.map (map_loc this) vars; + typ = this.typ this typ + } + | Pvc_coercion { ground; coercion } -> + Pvc_coercion { + ground = Option.map (this.typ this) ground; + coercion = this.typ this coercion + } + in Vb.mk (this.pat this pvb_pat) (this.expr this pvb_expr) + ?value_constraint:(Option.map map_ct pvb_constraint) ~loc:(this.location this pvb_loc) ~attrs:(this.attributes this pvb_attributes) ); diff --git a/vendor/parser-standard/parser.mly b/vendor/parser-standard/parser.mly index 697f757461..a303e14725 100644 --- a/vendor/parser-standard/parser.mly +++ b/vendor/parser-standard/parser.mly @@ -230,6 +230,11 @@ let unclosed opening_name opening_loc closing_name closing_loc = let expecting loc nonterm = raise Syntaxerr.(Error(Expecting(make_loc loc, nonterm))) +(* Continues to parse removed syntax +let removed_string_set loc = + raise(Syntaxerr.Error(Syntaxerr.Removed_string_set(make_loc loc))) +*) + (* Using the function [not_expecting] in a semantic action means that this syntactic form is recognized by the parser but is in fact incorrect. This idiom is used in a few places to produce ad hoc syntax error messages. *) @@ -304,7 +309,10 @@ let builtin_arraylike_name loc _ ~assign paren_kind n = let opname = if !Clflags.unsafe then "unsafe_" ^ opname else opname in let prefix = match paren_kind with | Paren -> Lident "Array" - | Bracket -> Lident "String" + | Bracket -> + (* Syntax removed in 5.1. if assign then removed_string_set loc + else *) + Lident "String" | Brace -> let submodule_name = match n with | One -> "Array1" @@ -501,6 +509,7 @@ let extra_rhs_core_type ct ~pos = type let_binding = { lb_pattern: pattern; lb_expression: expression; + lb_constraint: value_constraint option; lb_is_pun: bool; lb_attributes: attributes; lb_docs: docs Lazy.t; @@ -512,10 +521,11 @@ type let_bindings = lbs_rec: rec_flag; lbs_extension: string Asttypes.loc option } -let mklb first ~loc (p, e, is_pun) attrs = +let mklb first ~loc (p, e, typ, is_pun) attrs = { lb_pattern = p; lb_expression = e; + lb_constraint=typ; lb_is_pun = is_pun; lb_attributes = attrs; lb_docs = symbol_docs_lazy loc; @@ -543,7 +553,7 @@ let val_of_let_bindings ~loc lbs = Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes ~docs:(Lazy.force lb.lb_docs) ~text:(Lazy.force lb.lb_text) - lb.lb_pattern lb.lb_expression) + ?value_constraint:lb.lb_constraint lb.lb_pattern lb.lb_expression) lbs.lbs_bindings in let str = mkstr ~loc (Pstr_value(lbs.lbs_rec, List.rev bindings)) in @@ -556,7 +566,7 @@ let expr_of_let_bindings ~loc lbs body = List.map (fun lb -> Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes - lb.lb_pattern lb.lb_expression) + ?value_constraint:lb.lb_constraint lb.lb_pattern lb.lb_expression) lbs.lbs_bindings in mkexp_attrs ~loc (Pexp_let(lbs.lbs_rec, List.rev bindings, body)) @@ -567,7 +577,7 @@ let class_of_let_bindings ~loc lbs body = List.map (fun lb -> Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes - lb.lb_pattern lb.lb_expression) + ?value_constraint:lb.lb_constraint lb.lb_pattern lb.lb_expression) lbs.lbs_bindings in (* Our use of let_bindings(no_ext) guarantees the following: *) @@ -1323,10 +1333,9 @@ module_expr: | (* In a functor application, the actual argument must be parenthesized. *) me1 = module_expr me2 = paren_module_expr { Pmod_apply(me1, me2) } - | (* Application to unit is sugar for application to an empty structure. *) - me1 = module_expr LPAREN RPAREN - { (* TODO review mkmod location *) - Pmod_apply(me1, mkmod ~loc:$sloc (Pmod_structure [])) } + | (* Functor applied to unit. *) + me = module_expr LPAREN RPAREN + { Pmod_apply_unit me } | (* An extension. *) ex = extension { Pmod_extension ex } @@ -2525,42 +2534,39 @@ labeled_simple_expr: ; let_binding_body_no_punning: let_ident strict_binding - { ($1, $2) } + { ($1, $2, None) } | let_ident type_constraint EQUAL seq_expr { let v = $1 in (* PR#7344 *) let t = match $2 with - Some t, None -> t - | _, Some t -> t + Some t, None -> + Pvc_constraint { locally_abstract_univars = []; typ=t } + | ground, Some coercion -> Pvc_coercion { ground; coercion} | _ -> assert false in - let loc = Location.(t.ptyp_loc.loc_start, t.ptyp_loc.loc_end) in - let typ = ghtyp ~loc (Ptyp_poly([],t)) in - let patloc = ($startpos($1), $endpos($2)) in - (ghpat ~loc:patloc (Ppat_constraint(v, typ)), - mkexp_constraint ~loc:$sloc $4 $2) } + (v, $4, Some t) + } | let_ident COLON poly(core_type) EQUAL seq_expr - { let patloc = ($startpos($1), $endpos($3)) in - (ghpat ~loc:patloc - (Ppat_constraint($1, ghtyp ~loc:($loc($3)) $3)), - $5) } + { + let t = ghtyp ~loc:($loc($3)) $3 in + ($1, $5, Some (Pvc_constraint { locally_abstract_univars = []; typ=t })) + } | let_ident COLON TYPE lident_list DOT core_type EQUAL seq_expr - { let exp, poly = - wrap_type_annotation ~loc:$sloc $4 $6 $8 in - let loc = ($startpos($1), $endpos($6)) in - (ghpat ~loc (Ppat_constraint($1, poly)), exp) } + { let constraint' = + Pvc_constraint { locally_abstract_univars=$4; typ = $6} + in + ($1, $8, Some constraint') } | pattern_no_exn EQUAL seq_expr - { ($1, $3) } + { ($1, $3, None) } | simple_pattern_not_ident COLON core_type EQUAL seq_expr - { let loc = ($startpos($1), $endpos($3)) in - (ghpat ~loc (Ppat_constraint($1, $3)), $5) } + { ($1, $5, Some(Pvc_constraint { locally_abstract_univars=[]; typ=$3 })) } ; let_binding_body: | let_binding_body_no_punning - { let p,e = $1 in (p,e,false) } + { let p,e,c = $1 in (p,e,c,false) } /* BEGIN AVOID */ | val_ident %prec below_HASH - { (mkpatvar ~loc:$loc $1, mkexpvar ~loc:$loc $1, true) } + { (mkpatvar ~loc:$loc $1, mkexpvar ~loc:$loc $1, None, true) } (* The production that allows puns is marked so that [make list-parse-errors] does not attempt to exploit it. That would be problematic because it would then generate bindings such as [let x], which are rejected by the diff --git a/vendor/parser-standard/parsetree.mli b/vendor/parser-standard/parsetree.mli index 272f6bbebd..fba4d0fc56 100644 --- a/vendor/parser-standard/parsetree.mli +++ b/vendor/parser-standard/parsetree.mli @@ -961,7 +961,8 @@ and module_expr_desc = | Pmod_structure of structure (** [struct ... end] *) | Pmod_functor of functor_parameter * module_expr (** [functor(X : MT1) -> ME] *) - | Pmod_apply of module_expr * module_expr (** [ME1(ME2)] *) + | Pmod_apply of module_expr * module_expr (** [ME1(ME2)] *) + | Pmod_apply_unit of module_expr (** [ME1()] *) | Pmod_constraint of module_expr * module_type (** [(ME : MT)] *) | Pmod_unpack of expression (** [(val E)] *) | Pmod_extension of extension (** [[%id]] *) @@ -1006,13 +1007,30 @@ and structure_item_desc = | Pstr_attribute of attribute (** [[\@\@\@id]] *) | Pstr_extension of extension * attributes (** [[%%id]] *) +and value_constraint = + | Pvc_constraint of { + locally_abstract_univars:string loc list; + typ:core_type; + } + | Pvc_coercion of {ground:core_type option; coercion:core_type } + (** + - [Pvc_constraint { locally_abstract_univars=[]; typ}] + is a simple type constraint on a value binding: [ let x : typ] + - More generally, in [Pvc_constraint { locally_abstract_univars; typ}] + [locally_abstract_univars] is the list of locally abstract type + variables in [ let x: type a ... . typ ] + - [Pvc_coercion { ground=None; coercion }] represents [let x :> typ] + - [Pvc_coercion { ground=Some g; coercion }] represents [let x : g :> typ] + *) + and value_binding = { pvb_pat: pattern; pvb_expr: expression; + pvb_constraint: value_constraint option; pvb_attributes: attributes; pvb_loc: Location.t; - } + }(** [let pat : type_constraint = exp] *) and module_binding = { diff --git a/vendor/parser-standard/printast.ml b/vendor/parser-standard/printast.ml index 0fefc65f3d..bd59bfc4ae 100644 --- a/vendor/parser-standard/printast.ml +++ b/vendor/parser-standard/printast.ml @@ -789,6 +789,9 @@ and module_expr i ppf x = line i ppf "Pmod_apply\n"; module_expr i ppf me1; module_expr i ppf me2; + | Pmod_apply_unit me1 -> + line i ppf "Pmod_apply_unit\n"; + module_expr i ppf me1 | Pmod_constraint (me, mt) -> line i ppf "Pmod_constraint\n"; module_expr i ppf me; @@ -910,8 +913,24 @@ and value_binding i ppf x = line i ppf "\n"; attributes (i+1) ppf x.pvb_attributes; pattern (i+1) ppf x.pvb_pat; + Option.iter (value_constraint (i+1) ppf) x.pvb_constraint; expression (i+1) ppf x.pvb_expr +and value_constraint i ppf x = + let pp_sep ppf () = Format.fprintf ppf "@ "; in + let pp_newtypes = Format.pp_print_list fmt_string_loc ~pp_sep in + match x with + | Pvc_constraint { locally_abstract_univars = []; typ } -> + core_type i ppf typ + | Pvc_constraint { locally_abstract_univars=newtypes; typ} -> + line i ppf " %a.\n" pp_newtypes newtypes; + core_type i ppf typ + | Pvc_coercion { ground; coercion} -> + line i ppf "\n"; + option i core_type ppf ground; + core_type i ppf coercion; + + and binding_op i ppf x = line i ppf " %a %a" fmt_string_loc x.pbop_op fmt_location x.pbop_loc;