Skip to content

Commit f0934ab

Browse files
committed
Pull logic back into Jkind.ml
1 parent 7ba8720 commit f0934ab

File tree

5 files changed

+244
-143
lines changed

5 files changed

+244
-143
lines changed

typing/ctype.ml

+98
Original file line numberDiff line numberDiff line change
@@ -7216,3 +7216,101 @@ let constrain_decl_jkind env decl jkind =
72167216
match decl.type_manifest with
72177217
| None -> err
72187218
| Some ty -> constrain_type_jkind env ty jkind
7219+
7220+
let variant_field_types_and_modalities ~decl_params env cstrs =
7221+
let has_gadt_constructors = List.exists (fun cstr -> Option.is_some cstr.cd_res) cstrs in
7222+
let module Variant_parts = struct
7223+
type t =
7224+
{ cstr_arg_tys : type_expr list
7225+
; cstr_arg_modalities : Mode.Modality.Value.Const.t list
7226+
; params : type_expr list
7227+
; ret_args : type_expr list
7228+
; seen : Btype.TypeSet.t
7229+
}
7230+
7231+
let empty =
7232+
{ cstr_arg_tys = []
7233+
; cstr_arg_modalities = []
7234+
; params = []
7235+
; ret_args = []
7236+
; seen = Btype.TypeSet.empty
7237+
}
7238+
end in
7239+
let { Variant_parts.cstr_arg_tys; cstr_arg_modalities; ret_args; params; _ } =
7240+
List.fold_left
7241+
(fun { Variant_parts.cstr_arg_tys; cstr_arg_modalities; ret_args; params; seen } cstr ->
7242+
let cstr_arg_tys, cstr_arg_modalities =
7243+
match cstr.cd_args with
7244+
| Cstr_tuple args ->
7245+
List.fold_left
7246+
(fun (tys, ms) arg -> arg.ca_type :: tys, arg.ca_modalities :: ms)
7247+
(cstr_arg_tys, cstr_arg_modalities)
7248+
args
7249+
| Cstr_record lbls ->
7250+
List.fold_left
7251+
(fun (tys, ms) lbl -> lbl.ld_type :: tys, lbl.ld_modalities :: ms)
7252+
(cstr_arg_tys, cstr_arg_modalities)
7253+
lbls
7254+
in
7255+
(* Note: we're using polymorphic variants here to fake labeled tuples; we
7256+
can replace this with labeled tuples once we can build with a compiler
7257+
that supports those. *)
7258+
let `Args ret_args, `Params params, seen = match cstr.cd_res with
7259+
| None when not has_gadt_constructors -> `Args ret_args, `Params params, seen
7260+
| None -> `Args (decl_params @ ret_args), `Params (decl_params @ params), seen
7261+
| Some res ->
7262+
let existentials =
7263+
Datarepr.constructor_unbound_type_vars_excluding_row_variables cstr
7264+
|> Btype.TypeSet.to_seq
7265+
|> Seq.map Types.Transient_expr.type_expr
7266+
|> List.of_seq
7267+
in
7268+
let tof_kinds =
7269+
List.map
7270+
(fun ty ->
7271+
match get_desc ty with
7272+
| Tof_kind _ ->
7273+
(* We shouldn't be able to hit this, but it's harmless and
7274+
defensive to just keep these types the same. *)
7275+
ty
7276+
| Tvar { jkind; _ } | Tunivar { jkind; _ } ->
7277+
Btype.newgenty (Tof_kind jkind)
7278+
| _ -> Misc.fatal_error "constructor_unbound_type_vars must return Tvar or Tunivar")
7279+
existentials
7280+
in
7281+
(match Types.get_desc res with
7282+
| Tconstr (_, args, _) ->
7283+
List.fold_left2
7284+
(fun (`Args ret_args, `Params params, seen) arg param ->
7285+
if Btype.TypeSet.mem arg seen
7286+
then (`Args ret_args, `Params params, seen)
7287+
else match Types.get_desc arg, Types.get_desc param with
7288+
| Tvar _, Tvar _ ->
7289+
(`Args (arg :: ret_args), `Params (param :: params), Btype.TypeSet.add arg seen)
7290+
| _ -> (`Args ret_args, `Params params, seen))
7291+
(`Args (existentials @ ret_args), `Params (tof_kinds @ params), seen)
7292+
args
7293+
decl_params
7294+
| _ -> Misc.fatal_error "cd_res must be Tconstr")
7295+
in
7296+
{ Variant_parts.cstr_arg_tys; cstr_arg_modalities; params; ret_args; seen }
7297+
)
7298+
Variant_parts.empty
7299+
cstrs
7300+
in
7301+
let cstr_arg_tys =
7302+
if Misc.Stdlib.List.is_empty params
7303+
then cstr_arg_tys
7304+
else
7305+
match
7306+
apply
7307+
env
7308+
ret_args
7309+
(Btype.newgenty (Ttuple (List.map (fun ty -> None, ty) cstr_arg_tys)))
7310+
params
7311+
|> Types.get_desc
7312+
with
7313+
| Ttuple args -> List.map snd args
7314+
| _ -> Misc.fatal_error "apply should have returned a tuple here"
7315+
in
7316+
List.combine cstr_arg_tys cstr_arg_modalities

typing/datarepr.ml

+4
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,7 @@ let constructor_unbound_type_vars_excluding_row_variables cstr =
339339
(newgenty (Ttuple (List.map (fun ty -> None, ty) tyl)))
340340
in
341341
TypeSet.diff arg_vars_set bound_vars
342+
343+
let () =
344+
Jkind.constructor_unbound_type_vars_excluding_row_variables
345+
:= constructor_unbound_type_vars_excluding_row_variables

typing/jkind.ml

+126-10
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ let raw_type_expr : (Format.formatter -> type_expr -> unit) ref =
2929

3030
let set_raw_type_expr p = raw_type_expr := p
3131

32+
let constructor_unbound_type_vars_excluding_row_variables =
33+
ref (fun _ -> assert false)
34+
3235
module Nonempty_list = Misc.Nonempty_list
3336

3437
(* A *sort* is the information the middle/back ends need to be able to
@@ -2274,7 +2277,7 @@ let for_unboxed_record lbls =
22742277
in
22752278
Builtin.product ~why:Unboxed_record tys_modalities layouts
22762279

2277-
let for_boxed_variant cstrs =
2280+
let for_boxed_variant ~decl_params ~type_apply cstrs =
22782281
let open Types in
22792282
if List.for_all
22802283
(fun cstr ->
@@ -2298,16 +2301,129 @@ let for_boxed_variant cstrs =
22982301
~why:Boxed_variant
22992302
|> mark_best
23002303
in
2301-
let add_cstr_args cstr jkind =
2302-
match cstr.cd_args with
2303-
| Cstr_tuple args ->
2304-
List.fold_right
2305-
(fun arg ->
2306-
add_with_bounds ~modality:arg.ca_modalities ~type_expr:arg.ca_type)
2307-
args jkind
2308-
| Cstr_record lbls -> add_labels_as_with_bounds lbls jkind
2304+
let has_gadt_constructors =
2305+
List.exists (fun cstr -> Option.is_some cstr.cd_res) cstrs
2306+
in
2307+
let module Variant_parts = struct
2308+
type t =
2309+
{ cstr_arg_tys : type_expr list;
2310+
cstr_arg_modalities : Mode.Modality.Value.Const.t list;
2311+
params : type_expr list;
2312+
ret_args : type_expr list;
2313+
seen : Btype.TypeSet.t
2314+
}
2315+
2316+
let empty =
2317+
{ cstr_arg_tys = [];
2318+
cstr_arg_modalities = [];
2319+
params = [];
2320+
ret_args = [];
2321+
seen = Btype.TypeSet.empty
2322+
}
2323+
end in
2324+
let { Variant_parts.cstr_arg_tys; cstr_arg_modalities; ret_args; params; _ }
2325+
=
2326+
List.fold_left
2327+
(fun { Variant_parts.cstr_arg_tys;
2328+
cstr_arg_modalities;
2329+
ret_args;
2330+
params;
2331+
seen
2332+
} cstr ->
2333+
let cstr_arg_tys, cstr_arg_modalities =
2334+
match cstr.cd_args with
2335+
| Cstr_tuple args ->
2336+
List.fold_left
2337+
(fun (tys, ms) arg ->
2338+
arg.ca_type :: tys, arg.ca_modalities :: ms)
2339+
(cstr_arg_tys, cstr_arg_modalities)
2340+
args
2341+
| Cstr_record lbls ->
2342+
List.fold_left
2343+
(fun (tys, ms) lbl ->
2344+
lbl.ld_type :: tys, lbl.ld_modalities :: ms)
2345+
(cstr_arg_tys, cstr_arg_modalities)
2346+
lbls
2347+
in
2348+
(* Note: we're using polymorphic variants here to fake labeled tuples; we
2349+
can replace this with labeled tuples once we can build with a compiler
2350+
that supports those. *)
2351+
let `Args ret_args, `Params params, seen =
2352+
match cstr.cd_res with
2353+
| None when not has_gadt_constructors ->
2354+
`Args ret_args, `Params params, seen
2355+
| None ->
2356+
( `Args (decl_params @ ret_args),
2357+
`Params (decl_params @ params),
2358+
seen )
2359+
| Some res -> (
2360+
let existentials =
2361+
!constructor_unbound_type_vars_excluding_row_variables cstr
2362+
|> Btype.TypeSet.to_seq
2363+
|> Seq.map Types.Transient_expr.type_expr
2364+
|> List.of_seq
2365+
in
2366+
let tof_kinds =
2367+
List.map
2368+
(fun ty ->
2369+
match get_desc ty with
2370+
| Tof_kind _ ->
2371+
(* We shouldn't be able to hit this, but it's harmless and
2372+
defensive to just keep these types the same. *)
2373+
ty
2374+
| Tvar { jkind; _ } | Tunivar { jkind; _ } ->
2375+
Btype.newgenty (Tof_kind jkind)
2376+
| _ ->
2377+
Misc.fatal_error
2378+
"constructor_unbound_type_vars must return Tvar or \
2379+
Tunivar")
2380+
existentials
2381+
in
2382+
match Types.get_desc res with
2383+
| Tconstr (_, args, _) ->
2384+
List.fold_left2
2385+
(fun (`Args ret_args, `Params params, seen) arg param ->
2386+
if Btype.TypeSet.mem arg seen
2387+
then `Args ret_args, `Params params, seen
2388+
else
2389+
match Types.get_desc arg, Types.get_desc param with
2390+
| Tvar _, Tvar _ ->
2391+
( `Args (arg :: ret_args),
2392+
`Params (param :: params),
2393+
Btype.TypeSet.add arg seen )
2394+
| _ -> `Args ret_args, `Params params, seen)
2395+
( `Args (existentials @ ret_args),
2396+
`Params (tof_kinds @ params),
2397+
seen )
2398+
args decl_params
2399+
| _ -> Misc.fatal_error "cd_res must be Tconstr")
2400+
in
2401+
{ Variant_parts.cstr_arg_tys;
2402+
cstr_arg_modalities;
2403+
params;
2404+
ret_args;
2405+
seen
2406+
})
2407+
Variant_parts.empty cstrs
2408+
in
2409+
let cstr_arg_tys =
2410+
if Misc.Stdlib.List.is_empty params
2411+
then cstr_arg_tys
2412+
else
2413+
match
2414+
type_apply ret_args
2415+
(Btype.newgenty
2416+
(Ttuple (List.map (fun ty -> None, ty) cstr_arg_tys)))
2417+
params
2418+
|> Types.get_desc
2419+
with
2420+
| Ttuple args -> List.map snd args
2421+
| _ -> Misc.fatal_error "apply should have returned a tuple here"
23092422
in
2310-
List.fold_right add_cstr_args cstrs base
2423+
List.fold_left2
2424+
(fun jkind type_expr modality ->
2425+
add_with_bounds ~modality ~type_expr jkind)
2426+
base cstr_arg_tys cstr_arg_modalities
23112427

23122428
let for_boxed_tuple elts =
23132429
List.fold_right

typing/jkind.mli

+12-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ open Allowance
3333
* It is very easy to search for and replace when we have a better name.
3434
*)
3535

36+
val constructor_unbound_type_vars_excluding_row_variables :
37+
(Types.constructor_declaration -> Btype.TypeSet.t) ref
38+
3639
(* The externality mode. This tracks whether or not an expression is external
3740
to the type checker; something external to the type checker can be skipped
3841
during garbage collection.
@@ -496,7 +499,15 @@ val for_boxed_record : Types.label_declaration list -> Types.jkind_l
496499
val for_unboxed_record : Types.label_declaration list -> Types.jkind_l
497500

498501
(** Choose an appropriate jkind for a boxed variant type. *)
499-
val for_boxed_variant : Types.constructor_declaration list -> Types.jkind_l
502+
val for_boxed_variant :
503+
decl_params:Types.type_expr list ->
504+
type_apply:
505+
(Types.type_expr list ->
506+
Types.type_expr ->
507+
Types.type_expr list ->
508+
Types.type_expr) ->
509+
Types.constructor_declaration list ->
510+
Types.jkind_l
500511

501512
(** Choose an appropriate jkind for a boxed tuple type. *)
502513
val for_boxed_tuple : (string option * Types.type_expr) list -> Types.jkind_l

0 commit comments

Comments
 (0)