@@ -1466,6 +1466,14 @@ let instance_parameterized_type ?keep_names sch_args sch =
1466
1466
(ty_args, ty)
1467
1467
)
1468
1468
1469
+ let instance_parameterized_type_ex ?keep_names sch_args sch ~existentials =
1470
+ For_copy. with_scope (fun copy_scope ->
1471
+ let ty_args = List. map (fun t -> copy ?keep_names copy_scope t) sch_args in
1472
+ let ty = copy copy_scope sch in
1473
+ let existentials = List. map (copy copy_scope) existentials in
1474
+ (ty_args, ty, existentials)
1475
+ )
1476
+
1469
1477
let instance_parameterized_kind args jkind =
1470
1478
For_copy. with_scope (fun copy_scope ->
1471
1479
let ty_args = List. map (fun t -> copy copy_scope t) args in
@@ -1812,7 +1820,7 @@ let instance_prim (desc : Primitive.description) ty =
1812
1820
let unify_var' = (* Forward declaration *)
1813
1821
ref (fun _env _ty1 _ty2 -> assert false )
1814
1822
1815
- let subst env level priv abbrev oty params args body =
1823
+ let subst env level priv abbrev oty params args body ~ existentials =
1816
1824
if List. length params <> List. length args then raise Cannot_subst ;
1817
1825
let old_level = ! current_level in
1818
1826
current_level := level;
@@ -1829,14 +1837,16 @@ let subst env level priv abbrev oty params args body =
1829
1837
| _ -> assert false
1830
1838
in
1831
1839
abbreviations := abbrev;
1832
- let (params', body') = instance_parameterized_type params body in
1840
+ let (params', body', existentials') =
1841
+ instance_parameterized_type_ex params body ~existentials
1842
+ in
1833
1843
abbreviations := ref Mnil ;
1834
1844
let uenv = Expression {env; in_subst = true } in
1835
1845
try
1836
1846
! unify_var' uenv body0 body';
1837
1847
List. iter2 (! unify_var' uenv) params' args;
1838
1848
current_level := old_level;
1839
- body'
1849
+ ( body', existentials')
1840
1850
with Unify _ ->
1841
1851
current_level := old_level;
1842
1852
undo_abbrev () ;
@@ -1892,11 +1902,11 @@ let jkind_subst env level params args jkind =
1892
1902
it ensures invariants on types are enforced (decreasing levels), and we don't
1893
1903
care about efficiency here.
1894
1904
*)
1895
- let apply ?(use_current_level = false ) env params body args =
1905
+ let apply ?(use_current_level = false ) env params body args ~ existentials =
1896
1906
simple_abbrevs := Mnil ;
1897
1907
let level = if use_current_level then ! current_level else generic_level in
1898
1908
try
1899
- subst env level Public (ref Mnil ) None params args body
1909
+ subst env level Public (ref Mnil ) None params args body ~existentials
1900
1910
with
1901
1911
Cannot_subst -> raise Cannot_apply
1902
1912
@@ -1975,9 +1985,10 @@ let expand_abbrev_gen kind find_type_expansion env ty =
1975
1985
| (params , body , lv ) ->
1976
1986
(* prerr_endline
1977
1987
("add a "^string_of_kind kind^" expansion for "^Path.name path);*)
1978
- let ty' =
1988
+ let ty', _existentials =
1979
1989
try
1980
1990
subst env level kind abbrev (Some ty) params args body
1991
+ ~existentials: []
1981
1992
with Cannot_subst -> raise_escape_exn Constraint
1982
1993
in
1983
1994
(* For gadts, remember type as non exportable *)
@@ -2118,11 +2129,14 @@ let is_principal ty =
2118
2129
2119
2130
type unwrapped_type_expr =
2120
2131
{ ty : type_expr
2121
- ; is_open : bool
2132
+ ; bound_vars : TypeSet .t
2122
2133
; modality : Mode.Modality.Value.Const .t }
2123
2134
2124
2135
let mk_unwrapped_type_expr ty =
2125
- { ty; is_open = false ; modality = Mode.Modality.Value.Const. id }
2136
+ { ty; bound_vars = TypeSet. empty; modality = Mode.Modality.Value.Const. id }
2137
+
2138
+ let mk_bound_vars vars_list =
2139
+ TypeSet. of_list (List. map Transient_expr. repr vars_list)
2126
2140
2127
2141
type unbox_result =
2128
2142
(* unboxing process made a step: either an unboxing or removal of a [Tpoly] *)
@@ -2140,7 +2154,9 @@ let unbox_once env ty =
2140
2154
begin match Env. find_type p env with
2141
2155
| exception Not_found -> Missing p
2142
2156
| decl ->
2143
- let apply ty2 = apply env decl.type_params ty2 args in
2157
+ let apply ty2 existentials =
2158
+ apply env decl.type_params ty2 args ~existentials
2159
+ in
2144
2160
begin match find_unboxed_type decl with
2145
2161
| Some (ty2 , modality ) ->
2146
2162
let ty2 = match get_desc ty2 with Tpoly (t , _ ) -> t | _ -> ty2 in
@@ -2153,8 +2169,9 @@ let unbox_once env ty =
2153
2169
| Type_record_unboxed_product _ | Type_open -> []
2154
2170
| exception Not_found -> (* but we found it earlier! *) assert false
2155
2171
in
2156
- Stepped { ty = apply ty2;
2157
- is_open = not (Misc.Stdlib.List. is_empty existentials);
2172
+ let substed_ty, substed_existentials = apply ty2 existentials in
2173
+ Stepped { ty = substed_ty;
2174
+ bound_vars = mk_bound_vars substed_existentials;
2158
2175
modality }
2159
2176
| None -> begin match decl.type_kind with
2160
2177
| Type_record_unboxed_product ([_ ], Record_unboxed_product, _ ) ->
@@ -2163,8 +2180,8 @@ let unbox_once env ty =
2163
2180
| Type_record_unboxed_product
2164
2181
((_::_::_ as lbls), Record_unboxed_product , _) ->
2165
2182
Stepped_record_unboxed_product
2166
- (List. map (fun ld -> { ty = apply ld.ld_type;
2167
- is_open = false ;
2183
+ (List. map (fun ld -> { ty = fst ( apply ld.ld_type [] ) ;
2184
+ bound_vars = TypeSet. empty ;
2168
2185
modality = ld.ld_modalities }) lbls)
2169
2186
| Type_record_unboxed_product ([] , _ , _ ) ->
2170
2187
Misc. fatal_error " Ctype.unboxed_once: fieldless record"
@@ -2175,15 +2192,15 @@ let unbox_once env ty =
2175
2192
end
2176
2193
| Tpoly (ty , bound_vars ) ->
2177
2194
Stepped { ty;
2178
- is_open = not ( Misc.Stdlib.List. is_empty bound_vars) ;
2195
+ bound_vars = mk_bound_vars bound_vars;
2179
2196
modality = Mode.Modality.Value.Const. id }
2180
2197
| _ -> Final_result
2181
2198
2182
2199
let contained_without_boxing env ty =
2183
2200
match get_desc ty with
2184
2201
| Tconstr _ ->
2185
2202
begin match unbox_once env ty with
2186
- | Stepped { ty; is_open = _ ; modality = _ } -> [ty]
2203
+ | Stepped { ty; bound_vars = _ ; modality = _ } -> [ty]
2187
2204
| Stepped_record_unboxed_product tys ->
2188
2205
List. map (fun { ty; _ } -> ty) tys
2189
2206
| Final_result | Missing _ -> []
@@ -2198,28 +2215,30 @@ let contained_without_boxing env ty =
2198
2215
allowing us to return a type for which a definition was found even if
2199
2216
we eventually bottom out at a missing cmi file, or otherwise. *)
2200
2217
let rec get_unboxed_type_representation
2201
- ~is_open ~modality env ty_prev ty fuel =
2202
- if fuel < 0 then Error { ty; is_open ; modality }
2218
+ ~bound_vars ~modality env ty_prev ty fuel =
2219
+ if fuel < 0 then Error { ty; bound_vars ; modality }
2203
2220
else
2204
2221
(* We use expand_head_opt version of expand_head to get access
2205
2222
to the manifest type of private abbreviations. *)
2206
2223
let ty = expand_head_opt env ty in
2207
2224
match unbox_once env ty with
2208
- | Stepped { ty = ty2 ; is_open = is_open2 ; modality = modality2 } ->
2209
- let is_open = is_open || is_open2 in
2225
+ | Stepped { ty = ty2 ; bound_vars = bound_vars2 ; modality = modality2 } ->
2226
+ let bound_vars = TypeSet. union bound_vars bound_vars2 in
2210
2227
let modality =
2211
2228
Mode.Modality.Value.Const. concat modality ~then_: modality2
2212
2229
in
2213
2230
get_unboxed_type_representation
2214
- ~is_open ~modality env ty ty2 (fuel - 1 )
2231
+ ~bound_vars ~modality env ty ty2 (fuel - 1 )
2215
2232
| Stepped_record_unboxed_product _ | Final_result ->
2216
- Ok { ty; is_open ; modality }
2217
- | Missing _ -> Ok { ty = ty_prev; is_open ; modality }
2233
+ Ok { ty; bound_vars ; modality }
2234
+ | Missing _ -> Ok { ty = ty_prev; bound_vars ; modality }
2218
2235
2219
2236
let get_unboxed_type_representation env ty =
2220
2237
(* Do not give too much fuel: PR#7424 *)
2221
2238
get_unboxed_type_representation
2222
- ~is_open: false ~modality: Mode.Modality.Value.Const. id env ty ty 100
2239
+ ~bound_vars: TypeSet. empty
2240
+ ~modality: Mode.Modality.Value.Const. id
2241
+ env ty ty 100
2223
2242
2224
2243
let get_unboxed_type_approximation env ty =
2225
2244
match get_unboxed_type_representation env ty with
@@ -2250,12 +2269,14 @@ let rec estimate_type_jkind ~expand_component env ty =
2250
2269
| Tarrow _ -> Jkind. for_arrow
2251
2270
| Ttuple elts -> Jkind. for_boxed_tuple elts
2252
2271
| Tunboxed_tuple ltys ->
2253
- let is_open , tys_modalities =
2272
+ let bound_vars , tys_modalities =
2254
2273
List. fold_left_map
2255
- (fun is_open1 (_lbl , ty ) ->
2256
- let { ty; is_open = is_open2; modality } = expand_component ty in
2257
- (is_open1 || is_open2), (ty, modality))
2258
- false ltys
2274
+ (fun bound_vars1 (_lbl , ty ) ->
2275
+ let { ty; bound_vars = bound_vars2; modality } =
2276
+ expand_component ty
2277
+ in
2278
+ TypeSet. union bound_vars1 bound_vars2, (ty, modality))
2279
+ TypeSet. empty ltys
2259
2280
in
2260
2281
(* CR layouts v2.8: This pretty ridiculous use of [estimate_type_jkind]
2261
2282
just to throw most of it away will go away once we get [layout_of]. *)
@@ -2267,7 +2288,7 @@ let rec estimate_type_jkind ~expand_component env ty =
2267
2288
in
2268
2289
Jkind.Builtin. product
2269
2290
~why: Unboxed_tuple tys_modalities layouts |>
2270
- close_open_jkind ~expand_component ~is_open env
2291
+ close_open_jkind ~expand_component ~bound_vars env
2271
2292
| Tconstr (p , args , _ ) -> begin try
2272
2293
let type_decl = Env. find_type p env in
2273
2294
let jkind = type_decl.type_jkind in
@@ -2311,11 +2332,10 @@ let rec estimate_type_jkind ~expand_component env ty =
2311
2332
Jkind. disallow_right
2312
2333
| Tpackage _ -> Jkind.Builtin. value ~why: First_class_module
2313
2334
2314
- and close_open_jkind ~expand_component ~is_open env jkind =
2315
- if is_open (* if the type has free variables, we can't let these leak into
2316
- with-bounds *)
2317
- (* CR layouts v2.8: Do better, by tracking the actual free variables and
2318
- rounding only those variables up. *)
2335
+ and close_open_jkind ~expand_component ~bound_vars env jkind =
2336
+ if not (TypeSet. is_empty bound_vars)
2337
+ (* if the type has free variables, we can't let these leak into with-bounds *)
2338
+ (* CR layouts v2.8: Do better, by rounding only the bound variables up. *)
2319
2339
then
2320
2340
let jkind_of_type ty =
2321
2341
Some (estimate_type_jkind ~expand_component env ty)
@@ -2324,9 +2344,9 @@ and close_open_jkind ~expand_component ~is_open env jkind =
2324
2344
else jkind
2325
2345
2326
2346
let estimate_type_jkind_unwrapped
2327
- ~expand_component env { ty; is_open ; modality } =
2347
+ ~expand_component env { ty; bound_vars ; modality } =
2328
2348
estimate_type_jkind ~expand_component env ty |>
2329
- close_open_jkind ~expand_component ~is_open env |>
2349
+ close_open_jkind ~expand_component ~bound_vars env |>
2330
2350
Jkind. apply_modality_l modality
2331
2351
2332
2352
@@ -2385,15 +2405,19 @@ let constrain_type_jkind ~fixed env ty jkind =
2385
2405
later).
2386
2406
2387
2407
As this unboxes types, it might unbox an existential type. We thus keep
2388
- track of whether [ty] [is_open]. EDIT: This is actually pointless and
2389
- could be removed: #3684.
2408
+ track of the variables bound as we unbox (and look through [Tpoly]s.
2409
+ Comparing these variables in jkinds is fine, and they can't escape from
2410
+ this function (except harmlessly in error messages). However, we must be
2411
+ sure not to change the kinds of these bound variables; that's the only
2412
+ reason we track them here. See Test 47 in typing-layouts/basics.ml for an
2413
+ example.
2390
2414
2391
2415
As this unboxed types, it might also encounter modalities. These modalities
2392
2416
are accommodated by changing [jkind], the expected jkind of the type.
2393
2417
Trying to apply the modality to the jkind extracted from [ty] would be
2394
2418
wrong, as it would incorrectly change the jkind on a [Tvar] to mode-cross
2395
2419
more than necessary. *)
2396
- let rec loop ~fuel ~expanded ty ~is_open ty's_jkind jkind =
2420
+ let rec loop ~fuel ~expanded ty ~bound_vars ty's_jkind jkind =
2397
2421
(* Just succeed if we're comparing against [any] *)
2398
2422
if Jkind. is_obviously_max jkind then Ok () else
2399
2423
if fuel < 0 then
@@ -2405,7 +2429,8 @@ let constrain_type_jkind ~fixed env ty jkind =
2405
2429
(* The [ty's_jkind] we get here is an **r** jkind, necessary for
2406
2430
the call to [intersection_or_error]. And even if [ty] has unbound
2407
2431
variables, [ty's_jkind] can't have any variables in it, so we're OK. *)
2408
- | Tvar { jkind = ty's_jkind } when not fixed ->
2432
+ | Tvar { jkind = ty's_jkind } when not fixed &&
2433
+ not (TypeSet. mem ty bound_vars) ->
2409
2434
(* Unfixed tyvars are special in at least two ways:
2410
2435
2411
2436
1) Suppose we're processing [type 'a t = 'a list]. The ['a] on the
@@ -2434,9 +2459,9 @@ let constrain_type_jkind ~fixed env ty jkind =
2434
2459
2435
2460
(* Handle the [Tpoly] case out here so [Tvar]s wrapped in [Tpoly]s can get
2436
2461
the treatment above. *)
2437
- | Tpoly (t , bound_vars ) ->
2438
- let is_open = is_open || not ( Misc.Stdlib.List. is_empty bound_vars ) in
2439
- loop ~fuel ~expanded: false t ~is_open ty's_jkind jkind
2462
+ | Tpoly (t , bound_vars2 ) ->
2463
+ let bound_vars = TypeSet. union bound_vars (mk_bound_vars bound_vars2 ) in
2464
+ loop ~fuel ~expanded: false t ~bound_vars ty's_jkind jkind
2440
2465
2441
2466
| _ ->
2442
2467
match
@@ -2461,11 +2486,12 @@ let constrain_type_jkind ~fixed env ty jkind =
2461
2486
let recur ty's_jkinds jkinds =
2462
2487
let results =
2463
2488
Misc.Stdlib.List. map3
2464
- (fun { ty; is_open = _ ; modality } ty's_jkind jkind ->
2489
+ (fun { ty; bound_vars = bound_vars2 ; modality } ty's_jkind jkind ->
2490
+ let bound_vars = TypeSet. union bound_vars bound_vars2 in
2465
2491
let jkind =
2466
2492
Jkind. apply_modality_r modality jkind
2467
2493
in
2468
- loop ~fuel ~expanded: false ~is_open ty ty's_jkind jkind)
2494
+ loop ~fuel ~expanded: false ~bound_vars ty ty's_jkind jkind)
2469
2495
tys ty's_jkinds jkinds
2470
2496
in
2471
2497
if List. for_all Result. is_ok results
@@ -2498,7 +2524,7 @@ let constrain_type_jkind ~fixed env ty jkind =
2498
2524
if not expanded
2499
2525
then
2500
2526
let ty = expand_head_opt env ty in
2501
- loop ~fuel ~expanded: true ty ~is_open
2527
+ loop ~fuel ~expanded: true ty ~bound_vars
2502
2528
(estimate_type_jkind env ty) jkind
2503
2529
else
2504
2530
begin match unbox_once env ty with
@@ -2510,10 +2536,10 @@ let constrain_type_jkind ~fixed env ty jkind =
2510
2536
Error
2511
2537
(Jkind.Violation. of_ ~jkind_of_type
2512
2538
(Not_a_subjkind (ty's_jkind, jkind, sub_failure_reasons)))
2513
- | Stepped { ty; is_open = is_open2 ; modality } ->
2514
- let is_open = is_open || is_open2 in
2539
+ | Stepped { ty; bound_vars = bound_vars2 ; modality } ->
2540
+ let bound_vars = TypeSet. union bound_vars bound_vars2 in
2515
2541
let jkind = Jkind. apply_modality_r modality jkind in
2516
- loop ~fuel: (fuel - 1 ) ~expanded: false ty ~is_open
2542
+ loop ~fuel: (fuel - 1 ) ~expanded: false ty ~bound_vars
2517
2543
(estimate_type_jkind env ty) jkind
2518
2544
| Stepped_record_unboxed_product tys_modalities ->
2519
2545
product ~fuel: (fuel - 1 ) tys_modalities
@@ -2529,7 +2555,7 @@ let constrain_type_jkind ~fixed env ty jkind =
2529
2555
Error (Jkind.Violation. of_ ~jkind_of_type
2530
2556
(Not_a_subjkind (ty's_jkind, jkind, sub_failure_reasons)))
2531
2557
in
2532
- loop ~fuel: 100 ~expanded: false ty ~is_open: false
2558
+ loop ~fuel: 100 ~expanded: false ty ~bound_vars: TypeSet. empty
2533
2559
(estimate_type_jkind env ty) (Jkind. disallow_left jkind)
2534
2560
2535
2561
let type_sort ~why ~fixed env ty =
@@ -6163,10 +6189,10 @@ let rec build_subtype env (visited : transient_expr list)
6163
6189
begin try match get_desc t' with
6164
6190
Tobject _ when posi && not (opened_object t') ->
6165
6191
let cl_abbr, body = find_cltype_for_path env p in
6166
- let ty =
6192
+ let ty, _existentials =
6167
6193
try
6168
6194
subst env ! current_level Public abbrev None
6169
- cl_abbr.type_params tl body
6195
+ cl_abbr.type_params tl body ~existentials: []
6170
6196
with Cannot_subst -> assert false in
6171
6197
let ty1, tl1 =
6172
6198
match get_desc ty with
@@ -7142,6 +7168,9 @@ let print_global_state fmt global_state =
7142
7168
in
7143
7169
Format. fprintf fmt " @[<1>{@;%a}@]" print_fields global_state
7144
7170
7171
+ let apply ?use_current_level env params body args =
7172
+ fst (apply ?use_current_level env params body args ~existentials: [] )
7173
+
7145
7174
(* ******************************)
7146
7175
(* checking declaration jkinds *)
7147
7176
(* this is down here so it can use [is_equal] *)
0 commit comments