Skip to content

Commit be15048

Browse files
authored
AST: store arity in function type (rescript-lang#7195)
* AST: test storing arity in function type * WIP: extend types and type propagation with arity This needs some info from function definition that is not readily available. Better to postpone this until arity is explicit in function definitions. * Fix uncurried function type handling in FFI and type system Fix uncurried function type handling in FFI and type system This commit improves handling of uncurried function types, particularly in FFI and the type system: - Add arity information to @obj externals by returning arity from process_obj - Fix filter_arrow to properly handle arity in type unification - Remove invalid assert false in ast_uncurried.ml - Update type_function and type_application to properly handle arity information - Pass arity through to is_ignore function for consistent type checking These changes help ensure proper type checking and arity handling for uncurried functions, especially in FFI bindings using @obj. * Update TestPpx.res.jsout * Remove remaining uses of `type_to_arity`. * Move arity decoding to ast conversion. * Remove the arity parameter of type `function$`. * Update CHANGELOG.md * Update CHANGELOG.md
1 parent 65b1c68 commit be15048

File tree

97 files changed

+643
-595
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+643
-595
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
- Remove unused code from Location and Rescript_cpp modules. https://github.com/rescript-lang/rescript/pull/7150
3131
- Build with OCaml 5.2.1. https://github.com/rescript-lang/rescript-compiler/pull/7201
3232
- AST cleanup: Remove `Function$` entirely for function definitions. https://github.com/rescript-lang/rescript/pull/7200
33-
33+
- AST cleanup: store arity in function type https://github.com/rescript-lang/rescript/pull/7195
3434

3535
# 12.0.0-alpha.5
3636

analysis/reanalyze/src/DeadOptionalArgs.ml

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@ let addFunctionReference ~(locFrom : Location.t) ~(locTo : Location.t) =
3131
let rec hasOptionalArgs (texpr : Types.type_expr) =
3232
match texpr.desc with
3333
| _ when not (active ()) -> false
34-
| Tarrow (Optional _, _tFrom, _tTo, _) -> true
35-
| Tarrow (_, _tFrom, tTo, _) -> hasOptionalArgs tTo
34+
| Tarrow (Optional _, _tFrom, _tTo, _, _) -> true
35+
| Tarrow (_, _tFrom, tTo, _, _) -> hasOptionalArgs tTo
3636
| Tlink t -> hasOptionalArgs t
3737
| Tsubst t -> hasOptionalArgs t
3838
| _ -> false
3939

4040
let rec fromTypeExpr (texpr : Types.type_expr) =
4141
match texpr.desc with
4242
| _ when not (active ()) -> []
43-
| Tarrow (Optional s, _tFrom, tTo, _) -> s :: fromTypeExpr tTo
44-
| Tarrow (_, _tFrom, tTo, _) -> fromTypeExpr tTo
43+
| Tarrow (Optional s, _tFrom, tTo, _, _) -> s :: fromTypeExpr tTo
44+
| Tarrow (_, _tFrom, tTo, _, _) -> fromTypeExpr tTo
4545
| Tlink t -> fromTypeExpr t
4646
| Tsubst t -> fromTypeExpr t
4747
| _ -> []

analysis/src/CompletionBackEnd.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
898898
| [] -> tRet
899899
| (label, tArg) :: rest ->
900900
let restType = reconstructFunctionType rest tRet in
901-
{typ with desc = Tarrow (label, tArg, restType, Cok)}
901+
{typ with desc = Tarrow (label, tArg, restType, Cok, None)}
902902
in
903903
let rec processApply args labels =
904904
match (args, labels) with
@@ -1362,7 +1362,7 @@ let rec completeTypedValue ?(typeArgContext : typeArgContext option) ~rawOpens
13621362
| Tlink t1
13631363
| Tsubst t1
13641364
| Tpoly (t1, [])
1365-
| Tconstr (Pident {name = "function$"}, [t1; _], _) ->
1365+
| Tconstr (Pident {name = "function$"}, [t1], _) ->
13661366
fnReturnsTypeT t1
13671367
| Tarrow _ -> (
13681368
match TypeUtils.extractFunctionType ~env ~package:full.package t with

analysis/src/CompletionJsx.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ let getJsxLabels ~componentPath ~findTypeOfValue ~package =
238238
| Tlink t1
239239
| Tsubst t1
240240
| Tpoly (t1, [])
241-
| Tconstr (Pident {name = "function$"}, [t1; _], _) ->
241+
| Tconstr (Pident {name = "function$"}, [t1], _) ->
242242
getLabels t1
243243
| Tconstr (p, [propsType], _) when Path.name p = "React.component" -> (
244244
let rec getPropsType (t : Types.type_expr) =
@@ -251,15 +251,15 @@ let getJsxLabels ~componentPath ~findTypeOfValue ~package =
251251
match propsType |> getPropsType with
252252
| Some (path, typeArgs) -> getFields ~path ~typeArgs
253253
| None -> [])
254-
| Tarrow (Nolabel, {desc = Tconstr (path, typeArgs, _)}, _, _)
254+
| Tarrow (Nolabel, {desc = Tconstr (path, typeArgs, _)}, _, _, _)
255255
when Path.last path = "props" ->
256256
getFields ~path ~typeArgs
257257
| Tconstr (clPath, [{desc = Tconstr (path, typeArgs, _)}; _], _)
258258
when Path.name clPath = "React.componentLike"
259259
&& Path.last path = "props" ->
260260
(* JSX V4 external or interface *)
261261
getFields ~path ~typeArgs
262-
| Tarrow (Nolabel, typ, _, _) -> (
262+
| Tarrow (Nolabel, typ, _, _, _) -> (
263263
(* Component without the JSX PPX, like a make fn taking a hand-written
264264
type props. *)
265265
let rec digToConstr typ =

analysis/src/CreateInterface.ml

+8-4
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,9 @@ let printSignature ~extractor ~signature =
123123
Ctype.newconstr (Pdot (Pident (Ident.create "React"), "element", 0)) []
124124
in
125125
match typ.desc with
126-
| Tconstr (Pident {name = "function$"}, [typ; _], _) -> getComponentType typ
127-
| Tarrow (_, {desc = Tconstr (Path.Pident propsId, typeArgs, _)}, retType, _)
126+
| Tconstr (Pident {name = "function$"}, [typ], _) -> getComponentType typ
127+
| Tarrow
128+
(_, {desc = Tconstr (Path.Pident propsId, typeArgs, _)}, retType, _, _)
128129
when Ident.name propsId = "props" ->
129130
Some (typeArgs, retType)
130131
| Tconstr
@@ -173,14 +174,17 @@ let printSignature ~extractor ~signature =
173174
if labelDecl.ld_optional then Asttypes.Optional lblName
174175
else Labelled lblName
175176
in
176-
{retType with desc = Tarrow (lbl, propType, mkFunType rest, Cok)}
177+
{
178+
retType with
179+
desc = Tarrow (lbl, propType, mkFunType rest, Cok, None);
180+
}
177181
in
178182
let funType =
179183
if List.length labelDecls = 0 (* No props *) then
180184
let tUnit =
181185
Ctype.newconstr (Path.Pident (Ident.create "unit")) []
182186
in
183-
{retType with desc = Tarrow (Nolabel, tUnit, retType, Cok)}
187+
{retType with desc = Tarrow (Nolabel, tUnit, retType, Cok, None)}
184188
else mkFunType labelDecls
185189
in
186190
sigItemToString

analysis/src/Shared.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ let findTypeConstructors (tel : Types.type_expr list) =
5252
| Tconstr (path, args, _) ->
5353
addPath path;
5454
args |> List.iter loop
55-
| Tarrow (_, te1, te2, _) ->
55+
| Tarrow (_, te1, te2, _, _) ->
5656
loop te1;
5757
loop te2
5858
| Ttuple tel -> tel |> List.iter loop

analysis/src/SignatureHelp.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ let extractParameters ~signature ~typeStrForParser ~labelPrefixLen =
118118
ptyp_desc =
119119
Ptyp_constr
120120
( {txt = Lident "function$"},
121-
[({ptyp_desc = Ptyp_arrow _} as expr); _] );
121+
[({ptyp_desc = Ptyp_arrow _} as expr)] );
122122
};
123123
};
124124
} );
@@ -128,7 +128,7 @@ let extractParameters ~signature ~typeStrForParser ~labelPrefixLen =
128128
| {
129129
(* Gotcha: functions with multiple arugments are modelled as a series of single argument functions. *)
130130
Parsetree.ptyp_desc =
131-
Ptyp_arrow (argumentLabel, argumentTypeExpr, nextFunctionExpr);
131+
Ptyp_arrow (argumentLabel, argumentTypeExpr, nextFunctionExpr, _);
132132
ptyp_loc;
133133
} ->
134134
let startOffset =

analysis/src/TypeUtils.ml

+15-15
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ let debugLogTypeArgContext {env; typeArgs; typeParams} =
1010
let rec hasTvar (ty : Types.type_expr) : bool =
1111
match ty.desc with
1212
| Tvar _ -> true
13-
| Tarrow (_, ty1, ty2, _) -> hasTvar ty1 || hasTvar ty2
13+
| Tarrow (_, ty1, ty2, _, _) -> hasTvar ty1 || hasTvar ty2
1414
| Ttuple tyl -> List.exists hasTvar tyl
1515
| Tconstr (_, tyl, _) -> List.exists hasTvar tyl
1616
| Tobject (ty, _) -> hasTvar ty
@@ -36,7 +36,7 @@ let findTypeViaLoc ~full ~debug (loc : Location.t) =
3636

3737
let rec pathFromTypeExpr (t : Types.type_expr) =
3838
match t.desc with
39-
| Tconstr (Pident {name = "function$"}, [t; _], _) -> pathFromTypeExpr t
39+
| Tconstr (Pident {name = "function$"}, [t], _) -> pathFromTypeExpr t
4040
| Tconstr (path, _typeArgs, _)
4141
| Tlink {desc = Tconstr (path, _typeArgs, _)}
4242
| Tsubst {desc = Tconstr (path, _typeArgs, _)}
@@ -116,8 +116,8 @@ let instantiateType ~typeParams ~typeArgs (t : Types.type_expr) =
116116
| Tsubst t -> loop t
117117
| Tvariant rd -> {t with desc = Tvariant (rowDesc rd)}
118118
| Tnil -> t
119-
| Tarrow (lbl, t1, t2, c) ->
120-
{t with desc = Tarrow (lbl, loop t1, loop t2, c)}
119+
| Tarrow (lbl, t1, t2, c, arity) ->
120+
{t with desc = Tarrow (lbl, loop t1, loop t2, c, arity)}
121121
| Ttuple tl -> {t with desc = Ttuple (tl |> List.map loop)}
122122
| Tobject (t, r) -> {t with desc = Tobject (loop t, r)}
123123
| Tfield (n, k, t1, t2) -> {t with desc = Tfield (n, k, loop t1, loop t2)}
@@ -169,8 +169,8 @@ let instantiateType2 ?(typeArgContext : typeArgContext option)
169169
| Tsubst t -> loop t
170170
| Tvariant rd -> {t with desc = Tvariant (rowDesc rd)}
171171
| Tnil -> t
172-
| Tarrow (lbl, t1, t2, c) ->
173-
{t with desc = Tarrow (lbl, loop t1, loop t2, c)}
172+
| Tarrow (lbl, t1, t2, c, arity) ->
173+
{t with desc = Tarrow (lbl, loop t1, loop t2, c, arity)}
174174
| Ttuple tl -> {t with desc = Ttuple (tl |> List.map loop)}
175175
| Tobject (t, r) -> {t with desc = Tobject (loop t, r)}
176176
| Tfield (n, k, t1, t2) -> {t with desc = Tfield (n, k, loop t1, loop t2)}
@@ -242,8 +242,8 @@ let rec extractFunctionType ~env ~package typ =
242242
let rec loop ~env acc (t : Types.type_expr) =
243243
match t.desc with
244244
| Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> loop ~env acc t1
245-
| Tarrow (label, tArg, tRet, _) -> loop ~env ((label, tArg) :: acc) tRet
246-
| Tconstr (Pident {name = "function$"}, [t; _], _) ->
245+
| Tarrow (label, tArg, tRet, _, _) -> loop ~env ((label, tArg) :: acc) tRet
246+
| Tconstr (Pident {name = "function$"}, [t], _) ->
247247
extractFunctionType ~env ~package t
248248
| Tconstr (path, typeArgs, _) -> (
249249
match References.digConstructor ~env ~package path with
@@ -281,9 +281,9 @@ let rec extractFunctionType2 ?typeArgContext ~env ~package typ =
281281
let rec loop ?typeArgContext ~env acc (t : Types.type_expr) =
282282
match t.desc with
283283
| Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> loop ?typeArgContext ~env acc t1
284-
| Tarrow (label, tArg, tRet, _) ->
284+
| Tarrow (label, tArg, tRet, _, _) ->
285285
loop ?typeArgContext ~env ((label, tArg) :: acc) tRet
286-
| Tconstr (Pident {name = "function$"}, [t; _], _) ->
286+
| Tconstr (Pident {name = "function$"}, [t], _) ->
287287
extractFunctionType2 ?typeArgContext ~env ~package t
288288
| Tconstr (path, typeArgs, _) -> (
289289
match References.digConstructor ~env ~package path with
@@ -334,7 +334,7 @@ let rec extractType ?(printOpeningDebug = true)
334334
Some (Tstring env, typeArgContext)
335335
| Tconstr (Path.Pident {name = "exn"}, [], _) ->
336336
Some (Texn env, typeArgContext)
337-
| Tconstr (Pident {name = "function$"}, [t; _], _) -> (
337+
| Tconstr (Pident {name = "function$"}, [t], _) -> (
338338
match extractFunctionType2 ?typeArgContext t ~env ~package with
339339
| args, tRet, typeArgContext when args <> [] ->
340340
Some
@@ -910,14 +910,14 @@ let getArgs ~env (t : Types.type_expr) ~full =
910910
| Tlink t1
911911
| Tsubst t1
912912
| Tpoly (t1, [])
913-
| Tconstr (Pident {name = "function$"}, [t1; _], _) ->
913+
| Tconstr (Pident {name = "function$"}, [t1], _) ->
914914
getArgsLoop ~full ~env ~currentArgumentPosition t1
915-
| Tarrow (Labelled l, tArg, tRet, _) ->
915+
| Tarrow (Labelled l, tArg, tRet, _, _) ->
916916
(SharedTypes.Completable.Labelled l, tArg)
917917
:: getArgsLoop ~full ~env ~currentArgumentPosition tRet
918-
| Tarrow (Optional l, tArg, tRet, _) ->
918+
| Tarrow (Optional l, tArg, tRet, _, _) ->
919919
(Optional l, tArg) :: getArgsLoop ~full ~env ~currentArgumentPosition tRet
920-
| Tarrow (Nolabel, tArg, tRet, _) ->
920+
| Tarrow (Nolabel, tArg, tRet, _, _) ->
921921
(Unlabelled {argumentPosition = currentArgumentPosition}, tArg)
922922
:: getArgsLoop ~full ~env
923923
~currentArgumentPosition:(currentArgumentPosition + 1)

compiler/frontend/ast_comb.ml

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ let tuple_type_pair ?loc kind arity =
4040
match kind with
4141
| `Run -> (ty, [], ty)
4242
| `Make ->
43-
(Ast_compatible.arrow ?loc (Ast_literal.type_unit ?loc ()) ty, [], ty)
43+
( Ast_compatible.arrow ?loc ~arity:None (Ast_literal.type_unit ?loc ()) ty,
44+
[],
45+
ty )
4446
else
4547
let number = arity + 1 in
4648
let tys =
@@ -50,7 +52,7 @@ let tuple_type_pair ?loc kind arity =
5052
match tys with
5153
| result :: rest ->
5254
( Ext_list.reduce_from_left tys (fun r arg ->
53-
Ast_compatible.arrow ?loc arg r),
55+
Ast_compatible.arrow ?loc ~arity:None arg r),
5456
List.rev rest,
5557
result )
5658
| [] -> assert false

compiler/frontend/ast_compatible.ml

+6-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ open Parsetree
3030

3131
let default_loc = Location.none
3232

33-
let arrow ?loc ?attrs a b = Ast_helper.Typ.arrow ?loc ?attrs Nolabel a b
33+
let arrow ?loc ?attrs ~arity a b =
34+
Ast_helper.Typ.arrow ?loc ?attrs ~arity Nolabel a b
3435

3536
let apply_simple ?(loc = default_loc) ?(attrs = []) (fn : expression)
3637
(args : expression list) : expression =
@@ -94,16 +95,16 @@ let apply_labels ?(loc = default_loc) ?(attrs = []) fn
9495
Pexp_apply (fn, Ext_list.map args (fun (l, a) -> (Asttypes.Labelled l, a)));
9596
}
9697

97-
let label_arrow ?(loc = default_loc) ?(attrs = []) s a b : core_type =
98+
let label_arrow ?(loc = default_loc) ?(attrs = []) ~arity s a b : core_type =
9899
{
99-
ptyp_desc = Ptyp_arrow (Asttypes.Labelled s, a, b);
100+
ptyp_desc = Ptyp_arrow (Asttypes.Labelled s, a, b, arity);
100101
ptyp_loc = loc;
101102
ptyp_attributes = attrs;
102103
}
103104

104-
let opt_arrow ?(loc = default_loc) ?(attrs = []) s a b : core_type =
105+
let opt_arrow ?(loc = default_loc) ?(attrs = []) ~arity s a b : core_type =
105106
{
106-
ptyp_desc = Ptyp_arrow (Asttypes.Optional s, a, b);
107+
ptyp_desc = Ptyp_arrow (Asttypes.Optional s, a, b, arity);
107108
ptyp_loc = loc;
108109
ptyp_attributes = attrs;
109110
}

compiler/frontend/ast_compatible.mli

+8-1
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,17 @@ val fun_ :
9090
expression *)
9191

9292
val arrow :
93-
?loc:Location.t -> ?attrs:attrs -> core_type -> core_type -> core_type
93+
?loc:Location.t ->
94+
?attrs:attrs ->
95+
arity:Asttypes.arity ->
96+
core_type ->
97+
core_type ->
98+
core_type
9499

95100
val label_arrow :
96101
?loc:Location.t ->
97102
?attrs:attrs ->
103+
arity:Asttypes.arity ->
98104
string ->
99105
core_type ->
100106
core_type ->
@@ -103,6 +109,7 @@ val label_arrow :
103109
val opt_arrow :
104110
?loc:Location.t ->
105111
?attrs:attrs ->
112+
arity:Asttypes.arity ->
106113
string ->
107114
core_type ->
108115
core_type ->

compiler/frontend/ast_core_type.ml

+6-5
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ let from_labels ~loc arity labels : t =
9595
in
9696
Ext_list.fold_right2 labels tyvars result_type
9797
(fun label (* {loc ; txt = label }*) tyvar acc ->
98-
Ast_compatible.label_arrow ~loc:label.loc label.txt tyvar acc)
98+
Ast_compatible.label_arrow ~loc:label.loc ~arity:(Some arity) label.txt
99+
tyvar acc)
99100

100101
let make_obj ~loc xs = Typ.object_ ~loc xs Closed
101102

@@ -108,7 +109,7 @@ let make_obj ~loc xs = Typ.object_ ~loc xs Closed
108109
*)
109110
let rec get_uncurry_arity_aux (ty : t) acc =
110111
match ty.ptyp_desc with
111-
| Ptyp_arrow (_, _, new_ty) -> get_uncurry_arity_aux new_ty (succ acc)
112+
| Ptyp_arrow (_, _, new_ty, _) -> get_uncurry_arity_aux new_ty (succ acc)
112113
| Ptyp_poly (_, ty) -> get_uncurry_arity_aux ty acc
113114
| _ -> acc
114115

@@ -119,7 +120,7 @@ let rec get_uncurry_arity_aux (ty : t) acc =
119120
*)
120121
let get_uncurry_arity (ty : t) =
121122
match ty.ptyp_desc with
122-
| Ptyp_arrow (_, _, rest) -> Some (get_uncurry_arity_aux rest 1)
123+
| Ptyp_arrow (_, _, rest, _) -> Some (get_uncurry_arity_aux rest 1)
123124
| _ -> None
124125

125126
let get_curry_arity (ty : t) =
@@ -139,15 +140,15 @@ type param_type = {
139140
let mk_fn_type (new_arg_types_ty : param_type list) (result : t) : t =
140141
Ext_list.fold_right new_arg_types_ty result (fun {label; ty; attr; loc} acc ->
141142
{
142-
ptyp_desc = Ptyp_arrow (label, ty, acc);
143+
ptyp_desc = Ptyp_arrow (label, ty, acc, None);
143144
ptyp_loc = loc;
144145
ptyp_attributes = attr;
145146
})
146147

147148
let list_of_arrow (ty : t) : t * param_type list =
148149
let rec aux (ty : t) acc =
149150
match ty.ptyp_desc with
150-
| Ptyp_arrow (label, t1, t2) ->
151+
| Ptyp_arrow (label, t1, t2, _) ->
151152
aux t2
152153
(({label; ty = t1; attr = ty.ptyp_attributes; loc = ty.ptyp_loc}
153154
: param_type)

compiler/frontend/ast_core_type_class_type.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ let typ_mapper (self : Bs_ast_mapper.mapper) (ty : Parsetree.core_type) =
6969
| {
7070
ptyp_attributes;
7171
ptyp_desc =
72-
( Ptyp_arrow (label, args, body)
72+
( Ptyp_arrow (label, args, body, _)
7373
| Ptyp_constr
7474
(* function$<...> is re-wrapped around only in case Nothing below *)
7575
( {txt = Lident "function$"},
76-
[{ptyp_desc = Ptyp_arrow (label, args, body)}; _] ) );
76+
[{ptyp_desc = Ptyp_arrow (label, args, body, _)}] ) );
7777
(* let it go without regard label names,
7878
it will report error later when the label is not empty
7979
*)

0 commit comments

Comments
 (0)