@@ -381,7 +381,34 @@ let set_private_row env loc p decl =
381
381
in
382
382
set_type_desc rv (Tconstr (p, decl.type_params, ref Mnil ))
383
383
384
- let transl_labels ~new_var_jkind env univars closed lbls =
384
+ (* Makes sure a type is representable. When called with a type variable, will
385
+ lower [any] to a sort variable if [allow_unboxed = true], and to [value]
386
+ if [allow_unboxed = false]. *)
387
+ (* CR layouts: Many places where [check_representable] is called in this file
388
+ should be replaced with checks at the places where values of those types are
389
+ constructed. We've been conservative here in the first version. This is the
390
+ same issue as with arrows. *)
391
+ let check_representable ~why ~allow_unboxed env loc kloc typ =
392
+ match Ctype. type_sort ~why env typ with
393
+ (* CR layouts v5 : This is a convenient place to rule out non-value types in
394
+ structures that don't support them yet. (A callsite passes
395
+ [~allow_unboxed:true] to indicate that non-value types are allowed.)
396
+ When we support mixed blocks everywhere, this [check_representable]
397
+ will have outlived its usefulness and we can delete it.
398
+ * )
399
+ (* CR layouts v2 .5 : This rules out non-value types in [@@unboxed] types. No
400
+ real need to rule that out - I just haven't had time to write tests for it
401
+ yet. * )
402
+ | Ok s -> begin
403
+ if not allow_unboxed then
404
+ match Jkind.Sort. get_default_value s with
405
+ | Void | Value -> ()
406
+ | Float64 | Float32 | Word | Bits32 | Bits64 as const ->
407
+ raise (Error (loc, Invalid_jkind_in_block (typ, const, kloc)))
408
+ end
409
+ | Error err -> raise (Error (loc,Jkind_sort {kloc; typ; err}))
410
+
411
+ let transl_labels ~new_var_jkind ~allow_unboxed env univars closed lbls kloc =
385
412
assert (lbls <> [] );
386
413
let all_labels = ref String.Set. empty in
387
414
List. iter
@@ -421,6 +448,8 @@ let transl_labels ~new_var_jkind env univars closed lbls =
421
448
(fun ld ->
422
449
let ty = ld.ld_type.ctyp_type in
423
450
let ty = match get_desc ty with Tpoly (t ,[] ) -> t | _ -> ty in
451
+ check_representable ~why: (Label_declaration ld.ld_id)
452
+ ~allow_unboxed env ld.ld_loc kloc ty;
424
453
{Types. ld_id = ld.ld_id;
425
454
ld_mutable = ld.ld_mutable;
426
455
ld_global = ld.ld_global;
@@ -435,24 +464,42 @@ let transl_labels ~new_var_jkind env univars closed lbls =
435
464
lbls in
436
465
lbls, lbls'
437
466
438
- let transl_types_gf ~new_var_jkind env univars closed tyl =
467
+ let transl_types_gf ~new_var_jkind ~allow_unboxed
468
+ env loc univars closed tyl kloc =
439
469
let mk arg =
440
470
let cty = transl_simple_type ~new_var_jkind env ?univars ~closed Mode.Alloc.Const. legacy arg in
441
471
let gf = Typemode. transl_global_flags
442
472
(Jane_syntax.Mode_expr. of_attrs arg.ptyp_attributes |> fst) in
443
473
(cty, gf)
444
474
in
445
475
let tyl_gfl = List. map mk tyl in
446
- let tyl_gfl' = List. map (fun (cty , gf ) -> cty.ctyp_type, gf) tyl_gfl in
476
+ let tyl_gfl' = List. mapi (fun idx (cty , gf ) ->
477
+ check_representable ~why: (Constructor_declaration idx) ~allow_unboxed
478
+ env loc kloc cty.ctyp_type;
479
+ cty.ctyp_type, gf) tyl_gfl
480
+ in
447
481
tyl_gfl, tyl_gfl'
448
482
449
- let transl_constructor_arguments ~new_var_jkind env univars closed = function
483
+ let transl_constructor_arguments ~new_var_jkind ~unboxed
484
+ env loc univars closed = function
450
485
| Pcstr_tuple l ->
451
- let flds, flds' = transl_types_gf ~new_var_jkind env univars closed l in
452
- Types. Cstr_tuple flds',
453
- Cstr_tuple flds
486
+ let flds, flds' =
487
+ (* CR layouts: we forbid [@@unboxed] variants from being
488
+ non-value, see comment in [check_representable]. *)
489
+ transl_types_gf ~new_var_jkind ~allow_unboxed: (not unboxed)
490
+ env loc univars closed l (Cstr_tuple { unboxed })
491
+ in
492
+ Types. Cstr_tuple flds', Cstr_tuple flds
454
493
| Pcstr_record l ->
455
- let lbls, lbls' = transl_labels ~new_var_jkind env univars closed l in
494
+ let lbls, lbls' =
495
+ (* CR layouts: we forbid fields of inlined records from being
496
+ non-value, see comment in [check_representable].
497
+ When we allow mixed inline records, we still want to
498
+ disallow non-value types in unboxed records, so this
499
+ should become `not unboxed`, as in the `Pcstr_tuple` case. *)
500
+ transl_labels ~new_var_jkind ~allow_unboxed: false
501
+ env univars closed l (Inlined_record { unboxed })
502
+ in
456
503
Types. Cstr_record lbls',
457
504
Cstr_record lbls
458
505
@@ -462,7 +509,7 @@ let transl_constructor_arguments ~new_var_jkind env univars closed = function
462
509
defined types. It is updated later by [update_constructor_arguments_jkinds]
463
510
*)
464
511
let make_constructor
465
- env loc ~cstr_path ~type_path type_params (svars : _ Either.t )
512
+ env loc ~cstr_path ~type_path ~ unboxed type_params (svars : _ Either.t )
466
513
sargs sret_type =
467
514
let tvars = match svars with
468
515
| Left vars_only -> List. map (fun v -> v.txt, None ) vars_only
@@ -484,7 +531,8 @@ let make_constructor
484
531
match sret_type with
485
532
| None ->
486
533
let args, targs =
487
- transl_constructor_arguments ~new_var_jkind: Any env None true sargs
534
+ transl_constructor_arguments ~new_var_jkind: Any ~unboxed
535
+ env loc None true sargs
488
536
in
489
537
tvars, targs, None , args, None
490
538
| Some sret_type ->
@@ -510,7 +558,8 @@ let make_constructor
510
558
in
511
559
let univars = if closed then Some univar_list else None in
512
560
let args, targs =
513
- transl_constructor_arguments ~new_var_jkind: Sort env univars closed sargs
561
+ transl_constructor_arguments ~new_var_jkind: Sort ~unboxed
562
+ env loc univars closed sargs
514
563
in
515
564
let tret_type =
516
565
transl_simple_type ~new_var_jkind: Sort env ?univars ~closed Mode.Alloc.Const. legacy
@@ -759,7 +808,7 @@ let transl_declaration env sdecl (id, uid) =
759
808
attributes
760
809
in
761
810
let tvars, targs, tret_type, args, ret_type =
762
- make_constructor env scstr.pcd_loc
811
+ make_constructor ~unboxed: unbox env scstr.pcd_loc
763
812
~cstr_path: (Path. Pident name) ~type_path: path params
764
813
svars scstr.pcd_args scstr.pcd_res
765
814
in
@@ -813,7 +862,12 @@ let transl_declaration env sdecl (id, uid) =
813
862
in
814
863
Ttype_variant tcstrs, Type_variant (cstrs, rep), jkind
815
864
| Ptype_record lbls ->
816
- let lbls, lbls' = transl_labels ~new_var_jkind: Any env None true lbls in
865
+ let lbls, lbls' =
866
+ (* CR layouts: we forbid [@@unboxed] records from being
867
+ non-value, see comment in [check_representable]. *)
868
+ transl_labels ~new_var_jkind: Any ~allow_unboxed: (not unbox)
869
+ env None true lbls (Record { unboxed = unbox })
870
+ in
817
871
let rep, jkind =
818
872
(* Note this is inaccurate, using `Record_boxed` in cases where the
819
873
correct representation is [Record_float], [Record_ufloat], or
@@ -1089,45 +1143,13 @@ let check_coherence env loc dpath decl =
1089
1143
let check_abbrev env sdecl (id , decl ) =
1090
1144
(id, check_coherence env sdecl.ptype_loc (Path. Pident id) decl)
1091
1145
1092
- (* Makes sure a type is representable. Will lower "any" to "value". *)
1093
- (* CR layouts: In the places where this is used, we first call this to
1094
- ensure a type is representable, and then call [Ctype.type_jkind] to get the
1095
- most precise jkind. These could be combined into some new function
1096
- [Ctype.type_jkind_representable] that avoids duplicated work *)
1097
- (* CR layouts: Many places where [check_representable] is called in this file
1098
- should be replaced with checks at the places where values of those types are
1099
- constructed. We've been conservative here in the first version. This is the
1100
- same issue as with arrows. *)
1101
- let check_representable ~why ~allow_unboxed env loc kloc typ =
1102
- match Ctype. type_sort ~why env typ with
1103
- (* CR layouts v3 : This is a convenient place to rule out non-value types in
1104
- structures that don't support them yet. (A callsite passes
1105
- [~allow_unboxed:true] to indicate that non-value types are allowed.)
1106
- When we support mixed blocks everywhere, this [check_representable]
1107
- will have outlived its usefulness and we can delete it.
1108
- * )
1109
- (* CR layouts v2 .5 : This rules out non-value types in [@@unboxed] types. No
1110
- real need to rule that out - I just haven't had time to write tests for it
1111
- yet. * )
1112
- | Ok s -> begin
1113
- match Jkind.Sort. get_default_value s with
1114
- (* All calls to this are part of [update_decl_jkind], which happens after
1115
- all the defaulting, so we don't expect this actually defaults the
1116
- sort - we just want the [const]. *)
1117
- | Void | Value -> ()
1118
- | Float64 | Float32 | Word | Bits32 | Bits64 as const ->
1119
- if not allow_unboxed then
1120
- raise (Error (loc, Invalid_jkind_in_block (typ, const, kloc)))
1121
- end
1122
- | Error err -> raise (Error (loc,Jkind_sort {kloc; typ; err}))
1123
-
1124
1146
(* The [update_x_jkinds] functions infer more precise jkinds in the type kind,
1125
1147
including which fields of a record are void. This would be hard to do during
1126
1148
[transl_declaration] due to mutually recursive types.
1127
1149
*)
1128
1150
(* [update_label_jkinds] additionally returns whether all the jkinds
1129
1151
were void *)
1130
- let update_label_jkinds env loc lbls named ~ is_inlined =
1152
+ let update_label_jkinds env loc lbls named =
1131
1153
(* [named] is [Some jkinds] for top-level records (we will update the
1132
1154
jkinds) and [None] for inlined records. *)
1133
1155
(* CR layouts v5: it wouldn't be too hard to support records that are all
@@ -1137,15 +1159,8 @@ let update_label_jkinds env loc lbls named ~is_inlined =
1137
1159
| None -> fun _ _ -> ()
1138
1160
| Some jkinds -> fun idx jkind -> jkinds.(idx) < - jkind
1139
1161
in
1140
- let kloc =
1141
- if is_inlined
1142
- then Inlined_record { unboxed = false }
1143
- else Record { unboxed = false }
1144
- in
1145
1162
let lbls =
1146
- List. mapi (fun idx (Types. {ld_type; ld_id; ld_loc} as lbl ) ->
1147
- check_representable ~why: (Label_declaration ld_id)
1148
- ~allow_unboxed: (Option. is_some named) env ld_loc kloc ld_type;
1163
+ List. mapi (fun idx (Types. {ld_type} as lbl ) ->
1149
1164
let ld_jkind = Ctype. type_jkind env ld_type in
1150
1165
update idx ld_jkind;
1151
1166
{lbl with ld_jkind}
@@ -1163,13 +1178,11 @@ let update_constructor_arguments_jkinds env loc cd_args jkinds =
1163
1178
match cd_args with
1164
1179
| Types. Cstr_tuple tys ->
1165
1180
List. iteri (fun idx (ty ,_ ) ->
1166
- check_representable ~why: (Constructor_declaration idx) ~allow_unboxed: true
1167
- env loc (Cstr_tuple { unboxed = false }) ty;
1168
1181
jkinds.(idx) < - Ctype. type_jkind env ty) tys;
1169
1182
cd_args, Array. for_all Jkind. is_void_defaulting jkinds
1170
1183
| Types. Cstr_record lbls ->
1171
1184
let lbls, all_void =
1172
- update_label_jkinds env loc lbls None ~is_inlined: true
1185
+ update_label_jkinds env loc lbls None
1173
1186
in
1174
1187
jkinds.(0 ) < - Jkind. value ~why: Boxed_record ;
1175
1188
Types. Cstr_record lbls, all_void
@@ -1401,14 +1414,12 @@ let update_decl_jkind env dpath decl =
1401
1414
(* returns updated labels, updated rep, and updated jkind *)
1402
1415
let update_record_kind loc lbls rep =
1403
1416
match lbls, rep with
1404
- | [Types. {ld_type; ld_id; ld_loc} as lbl], Record_unboxed ->
1405
- check_representable ~why: (Label_declaration ld_id) ~allow_unboxed: false
1406
- env ld_loc (Record { unboxed = true }) ld_type;
1417
+ | [Types. {ld_type} as lbl], Record_unboxed ->
1407
1418
let ld_jkind = Ctype. type_jkind env ld_type in
1408
1419
[{lbl with ld_jkind}], Record_unboxed , ld_jkind
1409
1420
| _ , Record_boxed jkinds ->
1410
1421
let lbls, all_void =
1411
- update_label_jkinds env loc lbls (Some jkinds) ~is_inlined: false
1422
+ update_label_jkinds env loc lbls (Some jkinds)
1412
1423
in
1413
1424
let jkind = Jkind. for_boxed_record ~all_void in
1414
1425
let reprs =
@@ -1515,18 +1526,13 @@ let update_decl_jkind env dpath decl =
1515
1526
let update_variant_kind cstrs rep =
1516
1527
(* CR layouts: factor out duplication *)
1517
1528
match cstrs, rep with
1518
- | [{Types. cd_args;cd_loc } as cstr], Variant_unboxed -> begin
1529
+ | [{Types. cd_args} as cstr], Variant_unboxed -> begin
1519
1530
match cd_args with
1520
1531
| Cstr_tuple [ty,_] -> begin
1521
- check_representable ~why: (Constructor_declaration 0 )
1522
- ~allow_unboxed: false env cd_loc (Cstr_tuple { unboxed = true }) ty;
1523
1532
let jkind = Ctype. type_jkind env ty in
1524
1533
cstrs, Variant_unboxed , jkind
1525
1534
end
1526
- | Cstr_record [{ld_type; ld_id; ld_loc} as lbl] -> begin
1527
- check_representable ~why: (Label_declaration ld_id)
1528
- ~allow_unboxed: false env ld_loc (Inlined_record { unboxed = true })
1529
- ld_type;
1535
+ | Cstr_record [{ld_type} as lbl] -> begin
1530
1536
let ld_jkind = Ctype. type_jkind env ld_type in
1531
1537
[{ cstr with Types. cd_args =
1532
1538
Cstr_record [{ lbl with ld_jkind }] }],
@@ -2217,7 +2223,7 @@ let transl_extension_constructor_decl
2217
2223
env type_path typext_params loc id svars sargs sret_type =
2218
2224
let tvars, targs, tret_type, args, ret_type =
2219
2225
make_constructor env loc
2220
- ~cstr_path: (Pident id) ~type_path typext_params
2226
+ ~cstr_path: (Pident id) ~type_path ~unboxed: false typext_params
2221
2227
svars sargs sret_type
2222
2228
in
2223
2229
let num_args =
0 commit comments