Skip to content

AST: store the attributes directly on function arguments. #7660

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
33 changes: 8 additions & 25 deletions compiler/frontend/ast_core_type.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -131,39 +131,22 @@ 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 ->
let arity = List.length new_arg_types_ty in
{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
Expand All @@ -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
11 changes: 2 additions & 9 deletions compiler/frontend/ast_core_type.mli
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 7 additions & 7 deletions compiler/frontend/ast_derive_abstract.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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),
[] )
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
15 changes: 10 additions & 5 deletions compiler/frontend/ast_derive_js_mapper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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}

Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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 =
Expand Down
5 changes: 3 additions & 2 deletions compiler/frontend/ast_derive_projector.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 ->
Expand Down Expand Up @@ -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;
Expand Down
21 changes: 13 additions & 8 deletions compiler/frontend/ast_exp_handle_external.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}
Expand Down Expand Up @@ -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 ()]
| _ ->
Expand All @@ -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 =
Expand Down Expand Up @@ -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
Expand All @@ -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 =
Expand All @@ -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];
}
Expand Down
25 changes: 11 additions & 14 deletions compiler/frontend/ast_external_process.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
| {
Expand Down Expand Up @@ -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 -> (
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"

Expand Down Expand Up @@ -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 _ ->
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions compiler/frontend/ast_typ_uncurry.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 =
Expand Down
4 changes: 2 additions & 2 deletions compiler/ml/ast_mapper_from0.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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) -> (
Expand Down
2 changes: 1 addition & 1 deletion compiler/ml/parsetree.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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 (* _ *)
Expand Down
Loading