Skip to content

Commit ff1c573

Browse files
gabelevifacebook-github-bot
authored andcommitted
Refactor func_params.ml to give rest params their own field
Summary: This is the first in a series of changes around how rest parameters are handled. Up to now, we've been handling rest parameters using the `RestT` type. A rest parameter is just a `RestT` type in a list of parameters. It probably should be the last element in the list, but that's not really enforced. However the rest parameter shouldn't really be represented by a type. You can't pass around a rest parameter. Nothing will ever resolve to a rest parameter. A rest parameter is always immediately obvious syntactially. It's a bit of a hack to use a type to represent it. Instead, it should be held separately from the other params. This diff splits the rest param from the other params in func_params.ml Reviewed By: mroch Differential Revision: D4372165 fbshipit-source-id: f3f42e2ace7f820b86af2b68e76d1bf7db5fe6f5
1 parent 622d8b2 commit ff1c573

1 file changed

Lines changed: 31 additions & 21 deletions

File tree

src/typing/func_params.ml

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ type binding = string * Type.t * Loc.t
1010
type param =
1111
| Simple of Type.t * binding
1212
| Complex of Type.t * binding list
13-
| Rest of Type.t * binding
1413
type t = {
1514
list: param list;
15+
rest: (Type.t * binding) option;
1616
defaults: Ast.Expression.t Default.t SMap.t;
1717
}
1818

1919
let empty = {
2020
list = [];
21+
rest = None;
2122
defaults = SMap.empty
2223
}
2324

@@ -47,7 +48,8 @@ let mk cx type_params_map ~expr func =
4748
(* TODO: assert (not optional) *)
4849
let binding = name, t, loc in
4950
{ list = Simple (OptionalT t, binding) :: params.list;
50-
defaults = SMap.add name (Default.Expr expr) params.defaults })
51+
defaults = SMap.add name (Default.Expr expr) params.defaults;
52+
rest = params.rest; })
5153
| loc, _ ->
5254
let reason = mk_reason RDestructuring loc in
5355
let typeAnnotation = type_of_pattern pattern in
@@ -74,7 +76,11 @@ let mk cx type_params_map ~expr func =
7476
| None -> t (* TODO: assert (not optional) *)
7577
in
7678
let param = Complex (t, List.rev !rev_bindings) in
77-
{ list = param :: params.list; defaults = !defaults }
79+
{
80+
list = param :: params.list;
81+
defaults = !defaults;
82+
rest = params.rest;
83+
}
7884
) in
7985
let add_rest params pattern =
8086
match pattern with
@@ -87,8 +93,7 @@ let mk cx type_params_map ~expr func =
8793
let t =
8894
Anno.mk_type_annotation cx type_params_map reason typeAnnotation
8995
in
90-
let param = Rest (Anno.mk_rest cx t, (name, t, loc)) in
91-
{ params with list = param :: params.list }
96+
{ params with rest = Some (Anno.mk_rest cx t, (name, t, loc)) }
9297
| loc, _ ->
9398
Flow_js.add_output cx
9499
Flow_error.(EInternal (loc, RestArgumentNotIdentifierPattern));
@@ -126,8 +131,7 @@ let convert cx type_params_map func = Ast.Type.Function.(
126131
| None -> "_"
127132
| Some (_, name) -> name in
128133
let t = Anno.convert cx type_params_map typeAnnotation in
129-
let param = Rest (Anno.mk_rest cx t, (name, t, loc)) in
130-
{ params with list = param :: params.list }
134+
{ params with rest = Some (Anno.mk_rest cx t, (name, t, loc)) }
131135
in
132136
let (params, rest) = func.params in
133137
let params = List.fold_left add_param empty params in
@@ -139,22 +143,26 @@ let convert cx type_params_map func = Ast.Type.Function.(
139143
)
140144

141145
let names params =
142-
params.list |> List.map (function
143-
| Simple (_, (name, _, _))
144-
| Rest (_, (name, _, _)) -> name
145-
| Complex _ -> "_")
146+
let ret = params.list |> List.map (function
147+
| Simple (_, (name, _, _)) -> name
148+
| Complex _ -> "_") in
149+
match params.rest with
150+
| None -> ret
151+
| Some (_, (name, _, _)) -> ret @ [name]
146152

147153
let tlist params =
148-
params.list |> List.map (function
154+
let ret = params.list |> List.map (function
149155
| Simple (t, _)
150-
| Complex (t, _)
151-
| Rest (t, _) -> t)
156+
| Complex (t, _) -> t) in
157+
match params.rest with
158+
| None -> ret
159+
| Some (t, _) -> ret @ [t]
152160

153161
let iter f params =
154162
params.list |> List.iter (function
155-
| Simple (_, b)
156-
| Rest (_, b) -> f b
157-
| Complex (_, bs) -> List.iter f bs)
163+
| Simple (_, b) -> f b
164+
| Complex (_, bs) -> List.iter f bs);
165+
params.rest |> Option.iter ~f:(fun (_, b) -> f b)
158166

159167
let with_default name f params =
160168
match SMap.get name params.defaults with
@@ -168,7 +176,9 @@ let subst cx map params =
168176
| Simple (t, b) ->
169177
Simple (Flow.subst cx map t, subst_binding cx map b)
170178
| Complex (t, bs) ->
171-
Complex (Flow.subst cx map t, List.map (subst_binding cx map) bs)
172-
| Rest (t, b) ->
173-
Rest (Flow.subst cx map t, subst_binding cx map b)) in
174-
{ params with list }
179+
Complex (Flow.subst cx map t, List.map (subst_binding cx map) bs)) in
180+
let rest = match params.rest with
181+
| Some (rest_t, rest_binding) ->
182+
Some (Flow.subst cx map rest_t, subst_binding cx map rest_binding)
183+
| None -> None in
184+
{ params with list; rest; }

0 commit comments

Comments
 (0)