diff --git a/CHANGELOG.md b/CHANGELOG.md index 35f9a7995a..2d574ccc2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ #### :nail_care: Polish - Add missing backtick and spaces to `Belt.Map.map` doc comment. https://github.com/rescript-lang/rescript/pull/7632 +- AST: store the attributes directly on function arguments. https://github.com/rescript-lang/rescript/pull/7660 #### :house: Internal diff --git a/compiler/frontend/ast_core_type.ml b/compiler/frontend/ast_core_type.ml index 1c7c83c835..5e995a5634 100644 --- a/compiler/frontend/ast_core_type.ml +++ b/compiler/frontend/ast_core_type.ml @@ -95,7 +95,7 @@ let from_labels ~loc arity labels : t = in let args = Ext_list.map2 labels tyvars (fun label tyvar -> - {Parsetree.lbl = Asttypes.Labelled label; typ = tyvar}) + {Parsetree.attrs = []; lbl = Asttypes.Labelled label; typ = tyvar}) in Typ.arrows ~loc args result_type @@ -131,19 +131,10 @@ let get_curry_arity (ty : t) = let is_arity_one ty = get_curry_arity ty = 1 -type param_type = { - label: Asttypes.arg_label; - ty: Parsetree.core_type; - attr: Parsetree.attributes; - loc: loc; -} - -let mk_fn_type (new_arg_types_ty : param_type list) (result : t) : t = +let mk_fn_type ~loc (new_arg_types_ty : Parsetree.arg list) (result : t) : t = let t = - Ext_list.fold_right new_arg_types_ty result - (fun {label; ty; attr; loc} acc -> - Ast_helper.Typ.arrow ~loc ~attrs:attr ~arity:None - {lbl = label; typ = ty} acc) + Ext_list.fold_right new_arg_types_ty result (fun {lbl; typ; attrs} acc -> + Ast_helper.Typ.arrow ~loc ~attrs ~arity:None {attrs = []; lbl; typ} acc) in match t.ptyp_desc with | Ptyp_arrow arr -> @@ -151,19 +142,11 @@ let mk_fn_type (new_arg_types_ty : param_type list) (result : t) : t = {t with ptyp_desc = Ptyp_arrow {arr with arity = Some arity}} | _ -> t -let list_of_arrow (ty : t) : t * param_type list = +let list_of_arrow (ty : t) : t * Parsetree.arg list = let rec aux (ty : t) acc = match ty.ptyp_desc with | Ptyp_arrow {arg; ret; arity} when arity = None || acc = [] -> - aux ret - (({ - label = arg.lbl; - ty = arg.typ; - attr = ty.ptyp_attributes; - loc = ty.ptyp_loc; - } - : param_type) - :: acc) + aux ret (arg :: acc) | Ptyp_poly (_, ty) -> (* should not happen? *) Bs_syntaxerr.err ty.ptyp_loc Unhandled_poly_type @@ -173,6 +156,6 @@ let list_of_arrow (ty : t) : t * param_type list = let add_last_obj (ty : t) (obj : t) = let result, params = list_of_arrow ty in - mk_fn_type - (params @ [{label = Nolabel; ty = obj; attr = []; loc = obj.ptyp_loc}]) + mk_fn_type ~loc:obj.ptyp_loc + (params @ [{lbl = Nolabel; typ = obj; attrs = []}]) result diff --git a/compiler/frontend/ast_core_type.mli b/compiler/frontend/ast_core_type.mli index 15dc6aed32..71f98f450e 100644 --- a/compiler/frontend/ast_core_type.mli +++ b/compiler/frontend/ast_core_type.mli @@ -47,16 +47,9 @@ val get_uncurry_arity : t -> int option None -- means not a function *) -type param_type = { - label: Asttypes.arg_label; - ty: t; - attr: Parsetree.attributes; - loc: Location.t; -} +val mk_fn_type : loc:Location.t -> Parsetree.arg list -> t -> t -val mk_fn_type : param_type list -> t -> t - -val list_of_arrow : t -> t * param_type list +val list_of_arrow : t -> t * Parsetree.arg list (** fails when Ptyp_poly *) val add_last_obj : t -> t -> t diff --git a/compiler/frontend/ast_derive_abstract.ml b/compiler/frontend/ast_derive_abstract.ml index e11ac30a60..aa26fac59a 100644 --- a/compiler/frontend/ast_derive_abstract.ml +++ b/compiler/frontend/ast_derive_abstract.ml @@ -84,7 +84,7 @@ let handle_tdcl light (tdcl : Parsetree.type_declaration) : ( [], (if has_optional_field then Ast_helper.Typ.arrow ~loc ~arity:None - {lbl = Nolabel; typ = Ast_literal.type_unit ()} + {attrs = []; lbl = Nolabel; typ = Ast_literal.type_unit ()} core_type else core_type), [] ) @@ -116,19 +116,19 @@ let handle_tdcl light (tdcl : Parsetree.type_declaration) : if is_optional then let optional_type = Ast_core_type.lift_option_type pld_type in ( Ast_helper.Typ.arrow ~loc:pld_loc ~arity - {lbl = Asttypes.Optional pld_name; typ = pld_type} + {attrs = []; lbl = Asttypes.Optional pld_name; typ = pld_type} maker, Val.mk ~loc:pld_loc (if light then pld_name else {pld_name with txt = pld_name.txt ^ "Get"}) ~attrs:get_optional_attrs ~prim (Ast_helper.Typ.arrow ~loc ~arity:(Some 1) - {lbl = Nolabel; typ = core_type} + {attrs = []; lbl = Nolabel; typ = core_type} optional_type) :: acc ) else ( Ast_helper.Typ.arrow ~loc:pld_loc ~arity - {lbl = Asttypes.Labelled pld_name; typ = pld_type} + {attrs = []; lbl = Asttypes.Labelled pld_name; typ = pld_type} maker, Val.mk ~loc:pld_loc (if light then pld_name @@ -140,7 +140,7 @@ let handle_tdcl light (tdcl : Parsetree.type_declaration) : [External_arg_spec.dummy] Return_identity (Js_get {js_get_name = prim_as_name; js_get_scopes = []})) (Ast_helper.Typ.arrow ~loc ~arity:(Some 1) - {lbl = Nolabel; typ = core_type} + {attrs = []; lbl = Nolabel; typ = core_type} pld_type) :: acc ) in @@ -149,9 +149,9 @@ let handle_tdcl light (tdcl : Parsetree.type_declaration) : if is_current_field_mutable then let setter_type = Ast_helper.Typ.arrow ~arity:(Some 2) - {lbl = Nolabel; typ = core_type} + {attrs = []; lbl = Nolabel; typ = core_type} (Ast_helper.Typ.arrow ~arity:None - {lbl = Nolabel; typ = pld_type} (* setter *) + {attrs = []; lbl = Nolabel; typ = pld_type} (* setter *) (Ast_literal.type_unit ())) in Val.mk ~loc:pld_loc diff --git a/compiler/frontend/ast_derive_js_mapper.ml b/compiler/frontend/ast_derive_js_mapper.ml index 2915025c6f..6130195843 100644 --- a/compiler/frontend/ast_derive_js_mapper.ml +++ b/compiler/frontend/ast_derive_js_mapper.ml @@ -69,7 +69,9 @@ let erase_type_str = Str.primitive (Val.mk ~prim:["%identity"] {loc = noloc; txt = erase_type_lit} - (Ast_helper.Typ.arrow ~arity:(Some 1) {lbl = Nolabel; typ = any} any)) + (Ast_helper.Typ.arrow ~arity:(Some 1) + {attrs = []; lbl = Nolabel; typ = any} + any)) let unsafe_index = "_index" @@ -79,8 +81,11 @@ let unsafe_index_get = (Val.mk ~prim:[""] {loc = noloc; txt = unsafe_index} ~attrs:[Ast_attributes.get_index] - (Ast_helper.Typ.arrow ~arity:None {lbl = Nolabel; typ = any} - (Ast_helper.Typ.arrow ~arity:None {lbl = Nolabel; typ = any} any))) + (Ast_helper.Typ.arrow ~arity:None + {attrs = []; lbl = Nolabel; typ = any} + (Ast_helper.Typ.arrow ~arity:None + {attrs = []; lbl = Nolabel; typ = any} + any))) let unsafe_index_get_exp = Exp.ident {loc = noloc; txt = Lident unsafe_index} @@ -132,7 +137,7 @@ let app1 = Ast_compatible.app1 let app2 = Ast_compatible.app2 let ( ->~ ) a b = - Ast_helper.Typ.arrow ~arity:(Some 1) {lbl = Nolabel; typ = a} b + Ast_helper.Typ.arrow ~arity:(Some 1) {attrs = []; lbl = Nolabel; typ = a} b let raise_when_not_found_ident = Longident.Ldot (Lident Primitive_modules.util, "raiseWhenNotFound") @@ -305,7 +310,7 @@ let init () = let to_js_type result = Ast_comb.single_non_rec_val pat_to_js (Ast_helper.Typ.arrow ~arity:(Some 1) - {lbl = Nolabel; typ = core_type} + {attrs = []; lbl = Nolabel; typ = core_type} result) in let new_type, new_tdcl = diff --git a/compiler/frontend/ast_derive_projector.ml b/compiler/frontend/ast_derive_projector.ml index 0b4a4d8611..312c200f63 100644 --- a/compiler/frontend/ast_derive_projector.ml +++ b/compiler/frontend/ast_derive_projector.ml @@ -137,7 +137,7 @@ let init () = Ext_list.map label_declarations (fun {pld_name; pld_type} -> Ast_comb.single_non_rec_val ?attrs:gentype_attrs pld_name (Ast_helper.Typ.arrow ~arity:(Some 1) - {lbl = Nolabel; typ = core_type} + {attrs = []; lbl = Nolabel; typ = core_type} pld_type (*arity will alwys be 1 since these are single param functions*))) | Ptype_variant constructor_declarations -> @@ -170,7 +170,8 @@ let init () = {loc; txt = Ext_string.uncapitalize_ascii con_name} (Ext_list.fold_right pcd_args annotate_type (fun x acc -> Ast_helper.Typ.arrow ~arity:None - {lbl = Nolabel; typ = x} acc) + {attrs = []; lbl = Nolabel; typ = x} + acc) |> add_arity ~arity)) | Ptype_open | Ptype_abstract -> Ast_derive_util.not_applicable tdcl.ptype_loc deriving_name; diff --git a/compiler/frontend/ast_exp_handle_external.ml b/compiler/frontend/ast_exp_handle_external.ml index 551a1106e9..c34aff05fc 100644 --- a/compiler/frontend/ast_exp_handle_external.ml +++ b/compiler/frontend/ast_exp_handle_external.ml @@ -43,7 +43,7 @@ let handle_external loc (x : string) : Parsetree.expression = Ast_external_mk.local_external_apply loc ~pval_prim:["#raw_expr"] ~pval_type: (Ast_helper.Typ.arrow ~arity:(Some 1) - {lbl = Nolabel; typ = Ast_helper.Typ.any ()} + {attrs = []; lbl = Nolabel; typ = Ast_helper.Typ.any ()} (Ast_helper.Typ.any ())) [str_exp]; } @@ -72,7 +72,7 @@ let handle_debugger loc (payload : Ast_payload.t) = Ast_external_mk.local_external_apply loc ~pval_prim:["%debugger"] ~pval_type: (Ast_helper.Typ.arrow ~arity:(Some 1) - {lbl = Nolabel; typ = Ast_helper.Typ.any ()} + {attrs = []; lbl = Nolabel; typ = Ast_helper.Typ.any ()} (Ast_literal.type_unit ())) [Ast_literal.val_unit ~loc ()] | _ -> @@ -99,7 +99,7 @@ let handle_raw ~kind loc payload = Ast_external_mk.local_external_apply loc ~pval_prim:["#raw_expr"] ~pval_type: (Ast_helper.Typ.arrow ~arity:(Some 1) - {lbl = Nolabel; typ = Ast_helper.Typ.any ()} + {attrs = []; lbl = Nolabel; typ = Ast_helper.Typ.any ()} (Ast_helper.Typ.any ())) [exp]; pexp_attributes = @@ -128,11 +128,16 @@ let handle_ffi ~loc ~payload = let unit = Ast_literal.type_unit ~loc () in let rec arrow ~arity = if arity = 0 then - Ast_helper.Typ.arrow ~arity:None ~loc {lbl = Nolabel; typ = unit} any + Ast_helper.Typ.arrow ~arity:None ~loc + {attrs = []; lbl = Nolabel; typ = unit} + any else if arity = 1 then - Ast_helper.Typ.arrow ~arity:None ~loc {lbl = Nolabel; typ = any} any + Ast_helper.Typ.arrow ~arity:None ~loc + {attrs = []; lbl = Nolabel; typ = any} + any else - Ast_helper.Typ.arrow ~loc ~arity:None {lbl = Nolabel; typ = any} + Ast_helper.Typ.arrow ~loc ~arity:None + {attrs = []; lbl = Nolabel; typ = any} (arrow ~arity:(arity - 1)) in match !is_function with @@ -152,7 +157,7 @@ let handle_ffi ~loc ~payload = Ast_external_mk.local_external_apply loc ~pval_prim:["#raw_expr"] ~pval_type: (Ast_helper.Typ.arrow ~arity:(Some 1) - {lbl = Nolabel; typ = Ast_helper.Typ.any ()} + {attrs = []; lbl = Nolabel; typ = Ast_helper.Typ.any ()} (Ast_helper.Typ.any ())) [exp]; pexp_attributes = @@ -171,7 +176,7 @@ let handle_raw_structure loc payload = Ast_external_mk.local_external_apply loc ~pval_prim:["#raw_stmt"] ~pval_type: (Ast_helper.Typ.arrow ~arity:(Some 1) - {lbl = Nolabel; typ = Ast_helper.Typ.any ()} + {attrs = []; lbl = Nolabel; typ = Ast_helper.Typ.any ()} (Ast_helper.Typ.any ())) [exp]; } diff --git a/compiler/frontend/ast_external_process.ml b/compiler/frontend/ast_external_process.ml index e57e117289..1d43f0a2af 100644 --- a/compiler/frontend/ast_external_process.ml +++ b/compiler/frontend/ast_external_process.ml @@ -408,8 +408,7 @@ type response = { } let process_obj (loc : Location.t) (st : external_desc) (prim_name : string) - (arg_types_ty : Ast_core_type.param_type list) - (result_type : Ast_core_type.t) : + (arg_types_ty : Parsetree.arg list) (result_type : Ast_core_type.t) : int * Parsetree.core_type * External_ffi_types.t = match st with | { @@ -440,11 +439,10 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string) Ext_list.fold_right arg_types_ty ([], [], []) (fun param_type - (arg_labels, (arg_types : Ast_core_type.param_type list), result_types) + (arg_labels, (arg_types : Parsetree.arg list), result_types) -> - let arg_label = param_type.label in - let loc = param_type.loc in - let ty = param_type.ty in + let arg_label = param_type.lbl in + let ty = param_type.typ in let new_arg_label, new_arg_types, output_tys = match arg_label with | Nolabel -> ( @@ -459,7 +457,7 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string) | Labelled {txt = label} -> ( let field_name = match - Ast_attributes.iter_process_bs_string_as param_type.attr + Ast_attributes.iter_process_bs_string_as param_type.attrs with | Some alias -> alias | None -> label @@ -518,7 +516,7 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string) | Optional {txt = label} -> ( let field_name = match - Ast_attributes.iter_process_bs_string_as param_type.attr + Ast_attributes.iter_process_bs_string_as param_type.attrs with | Some alias -> alias | None -> label @@ -594,7 +592,7 @@ let process_obj (loc : Location.t) (st : external_desc) (prim_name : string) in ( List.length new_arg_types_ty, - Ast_core_type.mk_fn_type new_arg_types_ty result, + Ast_core_type.mk_fn_type ~loc new_arg_types_ty result, External_ffi_types.ffi_obj_create arg_kinds ) | _ -> Location.raise_errorf ~loc "Attribute found that conflicts with %@obj" @@ -942,11 +940,10 @@ let handle_attributes (loc : Bs_loc.t) (type_annotation : Parsetree.core_type) let splice = external_desc.splice in let arg_type_specs, new_arg_types_ty, arg_type_specs_length = Ext_list.fold_right arg_types_ty - (([], [], 0) - : External_arg_spec.params * Ast_core_type.param_type list * int) + (([], [], 0) : External_arg_spec.params * Parsetree.arg list * int) (fun param_type (arg_type_specs, arg_types, i) -> - let arg_label = param_type.label in - let ty = param_type.ty in + let arg_label = param_type.lbl in + let ty = param_type.typ in (if i = 0 && splice then match arg_label with | Optional _ -> @@ -1008,7 +1005,7 @@ let handle_attributes (loc : Bs_loc.t) (type_annotation : Parsetree.core_type) let return_wrapper = check_return_wrapper loc external_desc.return_wrapper result_type in - let fn_type = Ast_core_type.mk_fn_type new_arg_types_ty result_type in + let fn_type = Ast_core_type.mk_fn_type ~loc new_arg_types_ty result_type in ( build_uncurried_type ~arity:(List.length new_arg_types_ty) fn_type, External_ffi_types.ffi_bs arg_type_specs return_wrapper ffi, unused_attrs, diff --git a/compiler/frontend/ast_typ_uncurry.ml b/compiler/frontend/ast_typ_uncurry.ml index 6cd1338d29..8ccd76f6d2 100644 --- a/compiler/frontend/ast_typ_uncurry.ml +++ b/compiler/frontend/ast_typ_uncurry.ml @@ -32,7 +32,9 @@ let to_method_callback_type loc (mapper : Bs_ast_mapper.mapper) let first_arg = mapper.typ mapper first_arg in let typ = mapper.typ mapper typ in let meth_type = - Ast_helper.Typ.arrow ~loc ~arity:None {lbl = label; typ = first_arg} typ + Ast_helper.Typ.arrow ~loc ~arity:None + {attrs = []; lbl = label; typ = first_arg} + typ in let arity = Ast_core_type.get_uncurry_arity meth_type in match arity with @@ -58,7 +60,9 @@ let to_uncurry_type loc (mapper : Bs_ast_mapper.mapper) let typ = mapper.typ mapper typ in let fn_type = - Ast_helper.Typ.arrow ~loc ~arity:None {lbl = label; typ = first_arg} typ + Ast_helper.Typ.arrow ~loc ~arity:None + {attrs = []; lbl = label; typ = first_arg} + typ in let arity = Ast_core_type.get_uncurry_arity fn_type in let fn_type = diff --git a/compiler/ml/ast_mapper_from0.ml b/compiler/ml/ast_mapper_from0.ml index 15cadb1bda..4f1f6fff60 100644 --- a/compiler/ml/ast_mapper_from0.ml +++ b/compiler/ml/ast_mapper_from0.ml @@ -99,8 +99,8 @@ module T = struct | Ptyp_var s -> Typ.var ~loc ~attrs s | Ptyp_arrow (lbl, t1, t2) -> let lbl = Asttypes.to_arg_label lbl in - Typ.arrow ~loc ~attrs ~arity:None - {lbl; typ = sub.typ sub t1} + Typ.arrow ~loc ~arity:None + {attrs; lbl; typ = sub.typ sub t1} (sub.typ sub t2) | Ptyp_tuple tyl -> Typ.tuple ~loc ~attrs (List.map (sub.typ sub) tyl) | Ptyp_constr (lid, tl) -> ( diff --git a/compiler/ml/parsetree.ml b/compiler/ml/parsetree.ml index 2f39035aed..77194522e8 100644 --- a/compiler/ml/parsetree.ml +++ b/compiler/ml/parsetree.ml @@ -73,7 +73,7 @@ and core_type = { ptyp_attributes: attributes; (* ... [@id1] [@id2] *) } -and arg = {lbl: arg_label; typ: core_type} +and arg = {attrs: attributes; lbl: arg_label; typ: core_type} and core_type_desc = | Ptyp_any (* _ *) diff --git a/compiler/ml/pprintast.ml b/compiler/ml/pprintast.ml index 78b4a691b8..ff7f3f8c70 100644 --- a/compiler/ml/pprintast.ml +++ b/compiler/ml/pprintast.ml @@ -285,11 +285,15 @@ let tyvar f str = pp f "'%s" str let tyvar_loc f str = pp f "'%s" str.txt let string_quot f x = pp f "`%s" x -let rec type_with_label ctxt f (label, c) = - match label with - | Nolabel -> core_type1 ctxt f c (* otherwise parenthesize *) - | Labelled {txt = s} -> pp f "%s:%a" s (core_type1 ctxt) c - | Optional {txt = s} -> pp f "?%s:%a" s (core_type1 ctxt) c +let rec type_with_label ctxt f arg = + match arg.lbl with + | Nolabel -> + pp f "%a%a" (core_type1 ctxt) arg.typ (attributes ctxt) arg.attrs + (* otherwise parenthesize *) + | Labelled {txt = s} -> + pp f "%s:%a%a" s (core_type1 ctxt) arg.typ (attributes ctxt) arg.attrs + | Optional {txt = s} -> + pp f "?%s:%a%a" s (core_type1 ctxt) arg.typ (attributes ctxt) arg.attrs and core_type ctxt f x = if x.ptyp_attributes <> [] then @@ -300,7 +304,7 @@ and core_type ctxt f x = match x.ptyp_desc with | Ptyp_arrow {arg; ret; arity} -> pp f "@[<2>%a@;->@;%a%s@]" (* FIXME remove parens later *) - (type_with_label ctxt) (arg.lbl, arg.typ) (core_type ctxt) ret + (type_with_label ctxt) arg (core_type ctxt) ret (match arity with | None -> "" | Some n -> " (a:" ^ string_of_int n ^ ")") diff --git a/compiler/ml/printtyped.ml b/compiler/ml/printtyped.ml index efcd560dcc..064f0ab55c 100644 --- a/compiler/ml/printtyped.ml +++ b/compiler/ml/printtyped.ml @@ -152,6 +152,7 @@ let rec core_type i ppf x = | Ttyp_arrow (arg, ret, _) -> line i ppf "Ttyp_arrow\n"; arg_label i ppf arg.lbl; + attributes i ppf arg.attrs; core_type i ppf arg.typ; core_type i ppf ret | Ttyp_tuple l -> diff --git a/compiler/ml/typedtree.ml b/compiler/ml/typedtree.ml index 97bfe3848a..9ef328be4a 100644 --- a/compiler/ml/typedtree.ml +++ b/compiler/ml/typedtree.ml @@ -303,7 +303,7 @@ and core_type = { ctyp_attributes: attribute list; } -and arg = {lbl: Noloc.arg_label; typ: core_type} +and arg = {attrs: attributes; lbl: Noloc.arg_label; typ: core_type} and core_type_desc = | Ttyp_any diff --git a/compiler/ml/typedtree.mli b/compiler/ml/typedtree.mli index 71292362dc..6e6b1c5159 100644 --- a/compiler/ml/typedtree.mli +++ b/compiler/ml/typedtree.mli @@ -409,7 +409,7 @@ and core_type = { ctyp_attributes: attributes; } -and arg = {lbl: Noloc.arg_label; typ: core_type} +and arg = {attrs: attributes; lbl: Noloc.arg_label; typ: core_type} and core_type_desc = | Ttyp_any diff --git a/compiler/ml/typetexp.ml b/compiler/ml/typetexp.ml index 77cff06785..16308442dc 100644 --- a/compiler/ml/typetexp.ml +++ b/compiler/ml/typetexp.ml @@ -329,7 +329,7 @@ and transl_type_aux env policy styp = else ty1 in let ty = newty (Tarrow ({lbl; typ = ty1}, cty2.ctyp_type, Cok, arity)) in - ctyp (Ttyp_arrow ({lbl; typ = cty1}, cty2, arity)) ty + ctyp (Ttyp_arrow ({attrs = arg.attrs; lbl; typ = cty1}, cty2, arity)) ty | Ptyp_tuple stl -> assert (List.length stl >= 2); let ctys = List.map (transl_type env policy) stl in diff --git a/compiler/syntax/src/jsx_v4.ml b/compiler/syntax/src/jsx_v4.ml index e3391a63f3..b7ec8b15e3 100644 --- a/compiler/syntax/src/jsx_v4.ml +++ b/compiler/syntax/src/jsx_v4.ml @@ -918,20 +918,16 @@ let transform_structure_item ~config item = |> Option.map Jsx_common.typ_vars_of_core_type |> Option.value ~default:[] in - let rec get_prop_types types - ({ptyp_loc; ptyp_desc; ptyp_attributes} as full_type) = + let rec get_prop_types types ({ptyp_loc; ptyp_desc} as full_type) = match ptyp_desc with | Ptyp_arrow {arg; ret = {ptyp_desc = Ptyp_arrow _} as typ2} when is_labelled arg.lbl || is_optional arg.lbl -> - get_prop_types - ((arg.lbl, ptyp_attributes, ptyp_loc, arg.typ) :: types) - typ2 + get_prop_types ((arg.lbl, arg.attrs, ptyp_loc, arg.typ) :: types) typ2 | Ptyp_arrow {arg = {lbl = Nolabel}; ret} -> get_prop_types types ret | Ptyp_arrow {arg; ret = return_value} when is_labelled arg.lbl || is_optional arg.lbl -> ( return_value, - (arg.lbl, ptyp_attributes, return_value.ptyp_loc, arg.typ) :: types - ) + (arg.lbl, arg.attrs, return_value.ptyp_loc, arg.typ) :: types ) | _ -> (full_type, types) in let inner_type, prop_types = get_prop_types [] pval_type in @@ -1027,9 +1023,7 @@ let transform_signature_item ~config item = match ptyp_desc with | Ptyp_arrow {arg; ret = {ptyp_desc = Ptyp_arrow _} as rest} when is_optional arg.lbl || is_labelled arg.lbl -> - get_prop_types - ((arg.lbl, arg.typ.ptyp_attributes, ptyp_loc, arg.typ) :: types) - rest + get_prop_types ((arg.lbl, arg.attrs, ptyp_loc, arg.typ) :: types) rest | Ptyp_arrow { arg = @@ -1045,8 +1039,7 @@ let transform_signature_item ~config item = | Ptyp_arrow {arg; ret = return_value} when is_optional arg.lbl || is_labelled arg.lbl -> ( return_value, - (arg.lbl, arg.typ.ptyp_attributes, return_value.ptyp_loc, arg.typ) - :: types ) + (arg.lbl, arg.attrs, return_value.ptyp_loc, arg.typ) :: types ) | _ -> (full_type, types) in let inner_type, prop_types = get_prop_types [] pval_type in diff --git a/compiler/syntax/src/res_core.ml b/compiler/syntax/src/res_core.ml index 1d573460c4..cb4096661e 100644 --- a/compiler/syntax/src/res_core.ml +++ b/compiler/syntax/src/res_core.ml @@ -4039,7 +4039,8 @@ and parse_poly_type_expr ?current_type_name_path ?inline_types_context p = let typ = Ast_helper.Typ.var ~loc:var.loc var.txt in let return_type = parse_typ_expr ~alias:false p in let loc = mk_loc typ.Parsetree.ptyp_loc.loc_start p.prev_end_pos in - Ast_helper.Typ.arrow ~loc ~arity:(Some 1) {lbl = Nolabel; typ} + Ast_helper.Typ.arrow ~loc ~arity:(Some 1) + {attrs = []; lbl = Nolabel; typ} return_type | _ -> Ast_helper.Typ.var ~loc:var.loc var.txt) | _ -> assert false) @@ -4400,7 +4401,7 @@ and parse_es6_arrow_type ~attrs p = Parser.expect EqualGreater p; let return_type = parse_typ_expr ~alias:false p in let loc = mk_loc start_pos p.prev_end_pos in - Ast_helper.Typ.arrow ~loc ~attrs ~arity:None {lbl; typ} return_type + Ast_helper.Typ.arrow ~loc ~arity:None {attrs; lbl; typ} return_type | DocComment _ -> assert false | _ -> let parameters = parse_type_parameters p in @@ -4429,7 +4430,7 @@ and parse_es6_arrow_type ~attrs p = | _ -> arity in let t_arg = - Ast_helper.Typ.arrow ~loc ~attrs ~arity:None {lbl = arg_lbl; typ} t + Ast_helper.Typ.arrow ~loc ~arity:None {attrs; lbl = arg_lbl; typ} t in if param_num = 1 then (param_num - 1, Ast_uncurried.uncurried_type ~arity t_arg, 1) @@ -4493,7 +4494,9 @@ and parse_arrow_type_rest ~es6_arrow ~start_pos typ p = Parser.next p; let return_type = parse_typ_expr ~alias:false p in let loc = mk_loc start_pos p.prev_end_pos in - Ast_helper.Typ.arrow ~loc ~arity:(Some 1) {lbl = Nolabel; typ} return_type + Ast_helper.Typ.arrow ~loc ~arity:(Some 1) + {attrs = []; lbl = Nolabel; typ} + return_type | _ -> typ and parse_typ_expr_region p = @@ -5151,7 +5154,8 @@ and parse_type_equation_or_constr_decl p = let return_type = parse_typ_expr ~alias:false p in let loc = mk_loc uident_start_pos p.prev_end_pos in let arrow_type = - Ast_helper.Typ.arrow ~loc ~arity:(Some 1) {lbl = Nolabel; typ} + Ast_helper.Typ.arrow ~loc ~arity:(Some 1) + {attrs = []; lbl = Nolabel; typ} return_type in let typ = parse_type_alias p arrow_type in diff --git a/compiler/syntax/src/res_parsetree_viewer.ml b/compiler/syntax/src/res_parsetree_viewer.ml index 1deb497adb..f7264f6fb6 100644 --- a/compiler/syntax/src/res_parsetree_viewer.ml +++ b/compiler/syntax/src/res_parsetree_viewer.ml @@ -4,32 +4,22 @@ let arrow_type ?(max_arity = max_int) ct = let has_as_attr attrs = Ext_list.exists attrs (fun (x, _) -> x.Asttypes.txt = "as") in - let rec process attrs_before acc typ arity = + let rec process attrs_before acc typ max_arity = match typ with - | _ when arity < 0 -> (attrs_before, List.rev acc, typ) - | {ptyp_desc = Ptyp_arrow {arity = Some _}; ptyp_attributes = []} + | _ when max_arity < 0 -> (attrs_before, List.rev acc, typ) + | {ptyp_desc = Ptyp_arrow {arity = Some _; arg = {attrs = []}}} when acc <> [] -> (attrs_before, List.rev acc, typ) - | { - ptyp_desc = Ptyp_arrow {arg = {lbl = Nolabel} as arg; ret}; - ptyp_attributes = []; - } -> - let arg = ([], arg.lbl, arg.typ) in - process attrs_before (arg :: acc) ret (arity - 1) - | { - ptyp_desc = Ptyp_arrow {arg = {lbl = Nolabel}}; - ptyp_attributes = [({txt = "bs"}, _)]; - } -> - (* stop here, the uncurried attribute always indicates the beginning of an arrow function - * e.g. `(. int) => (. int)` instead of `(. int, . int)` *) - (attrs_before, List.rev acc, typ) + | {ptyp_desc = Ptyp_arrow {arg = {lbl = Nolabel; attrs = []} as arg; ret}} + -> + process attrs_before (arg :: acc) ret (max_arity - 1) | {ptyp_desc = Ptyp_arrow {arg = {lbl = Nolabel}}; ptyp_attributes = _attrs} as return_type -> let args = List.rev acc in (attrs_before, args, return_type) | { ptyp_desc = Ptyp_arrow {arg = {lbl = Labelled _ | Optional _} as arg; ret}; - ptyp_attributes = attrs; + ptyp_attributes = _attrs; } -> (* Res_core.parse_es6_arrow_type has a workaround that removed an extra arity for the function if the argument is a Ptyp_any with @as attribute i.e. ~x: @as(`{prop: value}`) _. @@ -40,16 +30,14 @@ let arrow_type ?(max_arity = max_int) ct = match arg.typ with | {ptyp_desc = Ptyp_any; ptyp_attributes = attrs1} when has_as_attr attrs1 -> - arity - | _ -> arity - 1 + max_arity + | _ -> max_arity - 1 in - let arg = (attrs, arg.lbl, arg.typ) in process attrs_before (arg :: acc) ret arity | typ -> (attrs_before, List.rev acc, typ) in match ct with - | {ptyp_desc = Ptyp_arrow {arg = {lbl = Nolabel}}; ptyp_attributes = attrs1} - as typ -> + | {ptyp_desc = Ptyp_arrow _; ptyp_attributes = attrs1} as typ -> process attrs1 [] {typ with ptyp_attributes = []} max_arity | typ -> process [] [] typ max_arity diff --git a/compiler/syntax/src/res_parsetree_viewer.mli b/compiler/syntax/src/res_parsetree_viewer.mli index d697d9fa3c..c50e3f2ce8 100644 --- a/compiler/syntax/src/res_parsetree_viewer.mli +++ b/compiler/syntax/src/res_parsetree_viewer.mli @@ -4,9 +4,7 @@ val arrow_type : ?max_arity:int -> Parsetree.core_type -> - Parsetree.attributes - * (Parsetree.attributes * Asttypes.arg_label * Parsetree.core_type) list - * Parsetree.core_type + Parsetree.attributes * Parsetree.arg list * Parsetree.core_type val functor_type : Parsetree.module_type -> diff --git a/compiler/syntax/src/res_printer.ml b/compiler/syntax/src/res_printer.ml index 17dd46f102..0dc8e49630 100644 --- a/compiler/syntax/src/res_printer.ml +++ b/compiler/syntax/src/res_printer.ml @@ -1702,7 +1702,7 @@ and print_typ_expr ?inline_record_definitions ~(state : State.t) in match args with | [] -> Doc.nil - | [([], Nolabel, n)] -> + | [{attrs = []; lbl = Nolabel; typ}] -> let has_attrs_before = not (attrs_before = []) in let attrs = if has_attrs_before then @@ -1710,8 +1710,8 @@ and print_typ_expr ?inline_record_definitions ~(state : State.t) else Doc.nil in let typ_doc = - let doc = print_typ_expr ~state n cmt_tbl in - match n.ptyp_desc with + let doc = print_typ_expr ~state typ cmt_tbl in + match typ.ptyp_desc with | Ptyp_arrow _ | Ptyp_tuple _ | Ptyp_alias _ -> add_parens doc | _ -> doc in @@ -2054,7 +2054,7 @@ and print_object_field ~state (field : Parsetree.object_field) cmt_tbl = (* es6 arrow type arg * type t = (~foo: string, ~bar: float=?, unit) => unit * i.e. ~foo: string, ~bar: float *) -and print_type_parameter ~state (attrs, lbl, typ) cmt_tbl = +and print_type_parameter ~state {attrs; lbl; typ} cmt_tbl = (* Converting .ml code to .res requires processing uncurried attributes *) let attrs = print_attributes ~state attrs cmt_tbl in let label = diff --git a/tests/syntax_tests/data/parsing/grammar/typexpr/expected/es6Arrow.res.txt b/tests/syntax_tests/data/parsing/grammar/typexpr/expected/es6Arrow.res.txt index aa42f44491..47f23df499 100644 --- a/tests/syntax_tests/data/parsing/grammar/typexpr/expected/es6Arrow.res.txt +++ b/tests/syntax_tests/data/parsing/grammar/typexpr/expected/es6Arrow.res.txt @@ -22,13 +22,13 @@ type nonrec t = f:(int -> string (a:1)) -> float (a:1) type nonrec t = f:(int -> string (a:1)) -> float type nonrec t = f:int -> string -> float (a:1) type nonrec t = - ((a:int -> ((b:int -> ((float)[@attr ]) -> unit)[@attrBeforeLblB ]) (a:3)) - [@attrBeforeLblA ]) + a:int[@attrBeforeLblA ] -> + b:int[@attrBeforeLblB ] -> ((float)[@attr ]) -> unit (a:3) type nonrec t = ((a:int -> ((b:int -> ((float)[@attr ]) -> unit (a:1) (a:1))[@attrBeforeLblB ]) (a:1)) [@attrBeforeLblA ]) -type nonrec t = ((a:int -> unit)[@attr ]) +type nonrec t = a:int[@attr ] -> unit type nonrec 'a getInitialPropsFn = < query: string dict ;req: 'a Js.t Js.Nullable.t > -> 'a Js.t Js.Promise.t (a:1) \ No newline at end of file diff --git a/tests/syntax_tests/data/ppx/react/expected/mangleKeyword.res.txt b/tests/syntax_tests/data/ppx/react/expected/mangleKeyword.res.txt index 1103c8267d..4413b38798 100644 --- a/tests/syntax_tests/data/ppx/react/expected/mangleKeyword.res.txt +++ b/tests/syntax_tests/data/ppx/react/expected/mangleKeyword.res.txt @@ -15,7 +15,7 @@ module C4A1 = { @res.jsxComponentProps @live type props<'T_open, 'T_type> = {@as("open") _open: 'T_open, @as("type") _type: 'T_type} - external make: @as("open") React.componentLike, React.element> = "default" + external make: React.componentLike, React.element> = "default" } let c4a0 = React.jsx(C4A0.make, {_open: "x", _type: "t"}) diff --git a/tests/syntax_tests/data/printer/typexpr/expected/arrow.res.txt b/tests/syntax_tests/data/printer/typexpr/expected/arrow.res.txt index 0392485cb0..cd0180e929 100644 --- a/tests/syntax_tests/data/printer/typexpr/expected/arrow.res.txt +++ b/tests/syntax_tests/data/printer/typexpr/expected/arrow.res.txt @@ -132,7 +132,7 @@ type t = @attr (foo, @attr2 ~f: bar, @attr3 ~f: baz) => unit type t = @attr (string => @attr (int => unit)) type t = @attr (string, int) => @attr (int, float) => unit type t = @attr (int => @attr (int, float) => @attr (unit => unit => unit)) -type t = (@attr @attr2 ~f: int, @attr3 ~g: float) => unit +type t = @attr (@attr2 ~f: int, @attr3 ~g: float) => unit type f = ( @attr @attr @attr @attr @attr @attr @attr @attr @attr ~f: superLong,