Skip to content

Allow type variables when spreading record type definitions #6309

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 14 commits into from
Jun 25, 2023
26 changes: 18 additions & 8 deletions jscomp/ml/typedecl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -452,17 +452,27 @@ let transl_declaration ~typeRecordAsObject env sdecl id =
lbl in
let rec process_lbls acc lbls lbls' = match lbls, lbls' with
| {ld_name = {txt = "..."}; ld_type} :: rest, _ :: rest' ->
let type_vars =
(* The type variables applied to the record spread itself. *)
let applied_type_vars =
match Ctype.repr ld_type.ctyp_type with
| {desc = Tpoly ({desc = Tconstr (_, tvars, _)}, _)} ->
tvars
|> List.filter_map (fun tvar ->
match Ctype.repr tvar with
| {desc = Tvar (Some name)} -> Some (name, tvar)
| _ -> None)
| {desc = Tpoly ({desc = Tconstr (_, tvars, _)}, _)} -> tvars
| _ -> [] in
(match Ctype.extract_concrete_typedecl env (extract ld_type.ctyp_type) with
(_p0, _p, {type_kind=Type_record (fields, _repr)}) ->
(_p0, _p, {type_kind=Type_record (fields, _repr); type_params}) ->
(* Track which type param in the record we're spreading
belongs to which type variable applied to the spread itself. *)
let idx = ref 0 in
let type_vars =
type_params
|> List.filter_map (fun t ->
let index = !idx in
idx := index + 1;
match t.desc with
| Tvar (Some tname) -> (
match List.nth_opt applied_type_vars index with
| None -> None
| Some t -> Some (tname, t))
| _ -> None) in
process_lbls
( fst acc @ (fields |> List.map (fun l -> mkLbl l ld_type type_vars)),
snd acc
Expand Down
5 changes: 5 additions & 0 deletions jscomp/test/record_type_spread.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions jscomp/test/record_type_spread.res
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,21 @@ let d: d<int> = {
c: None,
d: Some(Ok(1)),
}

type rn<'aaa> = {c: option<'aaa>}

type withRenamedTypeVariable<'bbb> = {
...rn<'bbb>,
}

let x: withRenamedTypeVariable<bool> = {
c: Some(true),
}

type rnAsString = {
...rn<string>,
}

let x: rnAsString = {
c: Some("hello"),
}