@@ -2100,9 +2100,14 @@ let expand_head_opt env ty =
2100
2100
let is_principal ty =
2101
2101
not ! Clflags. principal || get_level ty = generic_level
2102
2102
2103
+ type open_type_expr = { ty : type_expr ; is_open : bool }
2104
+
2105
+ let mk_open_type_expr ty vars =
2106
+ { ty; is_open = List. compare_length_with vars 0 <> 0 }
2107
+
2103
2108
type unbox_result =
2104
2109
(* unboxing process made a step: either an unboxing or removal of a [Tpoly] *)
2105
- | Stepped of type_expr
2110
+ | Stepped of open_type_expr
2106
2111
(* unboxing process unboxed a product. Invariant: length >= 2 *)
2107
2112
| Stepped_record_unboxed_product of type_expr list
2108
2113
(* no step to make; we're all done here *)
@@ -2120,7 +2125,16 @@ let unbox_once env ty =
2120
2125
begin match find_unboxed_type decl with
2121
2126
| Some ty2 ->
2122
2127
let ty2 = match get_desc ty2 with Tpoly (t , _ ) -> t | _ -> ty2 in
2123
- Stepped (apply ty2)
2128
+ let existentials =
2129
+ match Env. find_type_descrs p env with
2130
+ | Type_variant ([{ cstr_existentials } ], _ , _ ) -> cstr_existentials
2131
+ | Type_variant (_not_one , _ , _ ) ->
2132
+ Misc. fatal_error " Ctype.unbox_once: not just one constructor"
2133
+ | Type_abstract _ | Type_record _
2134
+ | Type_record_unboxed_product _ | Type_open -> []
2135
+ | exception Not_found -> (* but we found it earlier! *) assert false
2136
+ in
2137
+ Stepped (mk_open_type_expr (apply ty2) existentials)
2124
2138
| None -> begin match decl.type_kind with
2125
2139
| Type_record_unboxed_product ([_ ], Record_unboxed_product, _ ) ->
2126
2140
(* [find_unboxed_type] would have returned [Some] *)
@@ -2136,14 +2150,14 @@ let unbox_once env ty =
2136
2150
end
2137
2151
end
2138
2152
end
2139
- | Tpoly (ty , _ ) -> Stepped ty
2153
+ | Tpoly (ty , bound_vars ) -> Stepped (mk_open_type_expr ty bound_vars)
2140
2154
| _ -> Final_result
2141
2155
2142
2156
let contained_without_boxing env ty =
2143
2157
match get_desc ty with
2144
2158
| Tconstr _ ->
2145
2159
begin match unbox_once env ty with
2146
- | Stepped ty -> [ty]
2160
+ | Stepped { ty; _ } -> [ty]
2147
2161
| Stepped_record_unboxed_product tys -> tys
2148
2162
| Final_result | Missing _ -> []
2149
2163
end
@@ -2157,15 +2171,20 @@ let contained_without_boxing env ty =
2157
2171
allowing us to return a type for which a definition was found even if
2158
2172
we eventually bottom out at a missing cmi file, or otherwise. *)
2159
2173
let rec get_unboxed_type_representation env ty_prev ty fuel =
2160
- if fuel < 0 then Error ty else
2174
+ if fuel < 0 then Error { ty; is_open = false } else
2161
2175
(* We use expand_head_opt version of expand_head to get access
2162
2176
to the manifest type of private abbreviations. *)
2163
2177
let ty = expand_head_opt env ty in
2164
2178
match unbox_once env ty with
2165
- | Stepped ty2 ->
2166
- get_unboxed_type_representation env ty ty2 (fuel - 1 )
2167
- | Stepped_record_unboxed_product _ | Final_result -> Ok ty
2168
- | Missing _ -> Ok ty_prev
2179
+ | Stepped { ty = ty2 ; is_open = open1 } ->
2180
+ begin match get_unboxed_type_representation env ty ty2 (fuel - 1 ) with
2181
+ | Ok { ty = result ; is_open = open2 } ->
2182
+ Ok { ty = result; is_open = open1 || open2 }
2183
+ | Error _ as err -> err
2184
+ end
2185
+ | Stepped_record_unboxed_product _ | Final_result ->
2186
+ Ok { ty; is_open = false }
2187
+ | Missing _ -> Ok { ty = ty_prev; is_open = false }
2169
2188
2170
2189
let get_unboxed_type_representation env ty =
2171
2190
(* Do not give too much fuel: PR#7424 *)
@@ -2194,21 +2213,23 @@ let type_jkind_purely_if_principal' =
2194
2213
(* We parameterize [estimate_type_jkind] by a function
2195
2214
[expand_component] because some callers want expansion of types and others
2196
2215
don't. *)
2197
- let rec estimate_type_jkind ~expand_component env ty =
2216
+ let rec estimate_type_jkind ~( expand_component : type_expr -> open_type_expr ) env ty =
2198
2217
match get_desc ty with
2199
2218
| Tvar { jkind } -> Jkind. disallow_right jkind
2200
2219
| Tarrow _ -> Jkind. for_arrow
2201
2220
| Ttuple _ -> Jkind.Builtin. value ~why: Tuple
2202
2221
| Tunboxed_tuple ltys ->
2203
- let tys_modalities =
2204
- List. map (fun (_ , ty ) -> expand_component ty,
2205
- Mode.Modality.Value.Const. id) ltys
2222
+ let is_open, tys_modalities =
2223
+ List. fold_left_map
2224
+ (fun is_open1 (_lbl , ty ) ->
2225
+ let { ty; is_open = is_open2 } = expand_component ty in
2226
+ (is_open1 || is_open2), (ty, Mode.Modality.Value.Const. id))
2227
+ false ltys
2206
2228
in
2207
2229
(* CR layouts v2.8: This pretty ridiculous use of [estimate_type_jkind]
2208
2230
just to throw most of it away will go away once we get [layout_of]. *)
2209
2231
let jkinds =
2210
- List. map
2211
- (fun (ty , _ ) -> estimate_type_jkind ~expand_component env ty)
2232
+ List. map (fun (ty , _ ) -> estimate_type_jkind ~expand_component env ty)
2212
2233
tys_modalities
2213
2234
in
2214
2235
let layouts = List. map Jkind. extract_layout jkinds in
@@ -2220,7 +2241,8 @@ let rec estimate_type_jkind ~expand_component env ty =
2220
2241
| _ -> Misc. fatal_error
2221
2242
" Ctype.estimate_type_jkind: use of jkind_of_first_type \
2222
2243
with more than 1 type" )
2223
- ~why: Unboxed_tuple tys_modalities layouts
2244
+ ~why: Unboxed_tuple tys_modalities layouts |>
2245
+ close_open_jkind ~expand_component ~is_open env
2224
2246
| Tconstr (p , args , _ ) -> begin try
2225
2247
let type_decl = Env. find_type p env in
2226
2248
let jkind = type_decl.type_jkind in
@@ -2264,8 +2286,25 @@ let rec estimate_type_jkind ~expand_component env ty =
2264
2286
Jkind. disallow_right
2265
2287
| Tpackage _ -> Jkind.Builtin. value ~why: First_class_module
2266
2288
2289
+ and close_open_jkind ~expand_component ~is_open env jkind =
2290
+ if is_open (* if the type has free variables, we can't let these leak into
2291
+ with-bounds *)
2292
+ (* CR layouts v2.8: Do better, by tracking the actual free variables and
2293
+ rounding only those variables up. *)
2294
+ then
2295
+ let jkind_of_type ty =
2296
+ Some (estimate_type_jkind ~expand_component env ty)
2297
+ in
2298
+ Jkind. round_up ~jkind_of_type jkind |> Jkind. disallow_right
2299
+ else jkind
2300
+
2301
+ let estimate_type_jkind_open ~expand_component env { ty; is_open } =
2302
+ estimate_type_jkind ~expand_component env ty |>
2303
+ close_open_jkind ~expand_component ~is_open env
2304
+
2267
2305
let type_jkind env ty =
2268
- estimate_type_jkind ~expand_component: (get_unboxed_type_approximation env) env
2306
+ estimate_type_jkind_open
2307
+ ~expand_component: (get_unboxed_type_approximation env) env
2269
2308
(get_unboxed_type_approximation env ty)
2270
2309
2271
2310
(* CR layouts v2.8: This function is quite suspect. See Jane Street internal
@@ -2289,7 +2328,13 @@ let type_jkind_purely_if_principal env ty =
2289
2328
| false -> None
2290
2329
let () = type_jkind_purely_if_principal' := type_jkind_purely_if_principal
2291
2330
2292
- let estimate_type_jkind = estimate_type_jkind ~expand_component: Fun. id
2331
+ let estimate_type_jkind =
2332
+ let expand_component ty = { ty; is_open = false } in
2333
+ estimate_type_jkind ~expand_component
2334
+
2335
+ let estimate_type_jkind_open =
2336
+ let expand_component ty = { ty; is_open = false } in
2337
+ estimate_type_jkind_open ~expand_component
2293
2338
2294
2339
(* *** checking jkind relationships ****)
2295
2340
@@ -2315,8 +2360,11 @@ let constrain_type_jkind ~fixed env ty jkind =
2315
2360
ensure it's a valid argument to [t]. (We believe there are still loops
2316
2361
like this that can occur, though, and may need a more principled solution
2317
2362
later).
2363
+
2364
+ As this unboxes types, it might unbox an existential type. We thus keep
2365
+ track of whether [ty] [is_open].
2318
2366
*)
2319
- let rec loop ~fuel ~expanded ty ty's_jkind jkind =
2367
+ let rec loop ~fuel ~expanded ty ~ is_open ty's_jkind jkind =
2320
2368
(* Just succeed if we're comparing against [any] *)
2321
2369
if Jkind. is_obviously_max jkind then Ok () else
2322
2370
if fuel < 0 then
@@ -2326,7 +2374,8 @@ let constrain_type_jkind ~fixed env ty jkind =
2326
2374
else
2327
2375
match get_desc ty with
2328
2376
(* The [ty's_jkind] we get here is an **r** jkind, necessary for
2329
- the call to [intersection_or_error]. *)
2377
+ the call to [intersection_or_error]. And even if [ty] has unbound
2378
+ variables, [ty's_jkind] can't have any variables in it, so we're OK. *)
2330
2379
| Tvar { jkind = ty's_jkind } when not fixed ->
2331
2380
(* Unfixed tyvars are special in at least two ways:
2332
2381
@@ -2356,7 +2405,11 @@ let constrain_type_jkind ~fixed env ty jkind =
2356
2405
2357
2406
(* Handle the [Tpoly] case out here so [Tvar]s wrapped in [Tpoly]s can get
2358
2407
the treatment above. *)
2359
- | Tpoly (t , _ ) -> loop ~fuel ~expanded: false t ty's_jkind jkind
2408
+ | Tpoly (t , bound_vars ) ->
2409
+ let is_open =
2410
+ is_open || match bound_vars with | [] -> false | _ :: _ -> true
2411
+ in
2412
+ loop ~fuel ~expanded: false t ~is_open ty's_jkind jkind
2360
2413
2361
2414
| _ ->
2362
2415
match
@@ -2381,7 +2434,7 @@ let constrain_type_jkind ~fixed env ty jkind =
2381
2434
let recur ty's_jkinds jkinds =
2382
2435
let results =
2383
2436
Misc.Stdlib.List. map3
2384
- (loop ~fuel ~expanded: false ) tys ty's_jkinds jkinds
2437
+ (loop ~fuel ~expanded: false ~is_open ) tys ty's_jkinds jkinds
2385
2438
in
2386
2439
if List. for_all Result. is_ok results
2387
2440
then Ok ()
@@ -2413,7 +2466,8 @@ let constrain_type_jkind ~fixed env ty jkind =
2413
2466
if not expanded
2414
2467
then
2415
2468
let ty = expand_head_opt env ty in
2416
- loop ~fuel ~expanded: true ty (estimate_type_jkind env ty) jkind
2469
+ loop ~fuel ~expanded: true ty ~is_open
2470
+ (estimate_type_jkind_open env { ty; is_open }) jkind
2417
2471
else
2418
2472
begin match unbox_once env ty with
2419
2473
| Missing path -> Error (Jkind.Violation. of_
@@ -2424,9 +2478,10 @@ let constrain_type_jkind ~fixed env ty jkind =
2424
2478
Error
2425
2479
(Jkind.Violation. of_ ~jkind_of_type
2426
2480
(Not_a_subjkind (ty's_jkind, jkind, sub_failure_reasons)))
2427
- | Stepped ty ->
2428
- loop ~fuel: (fuel - 1 ) ~expanded: false ty
2429
- (estimate_type_jkind env ty) jkind
2481
+ | Stepped { ty; is_open = is_open2 } ->
2482
+ let is_open = is_open || is_open2 in
2483
+ loop ~fuel: (fuel - 1 ) ~expanded: false ty ~is_open
2484
+ (estimate_type_jkind_open env { ty; is_open }) jkind
2430
2485
| Stepped_record_unboxed_product tys ->
2431
2486
product ~fuel: (fuel - 1 ) tys
2432
2487
end
@@ -2440,7 +2495,8 @@ let constrain_type_jkind ~fixed env ty jkind =
2440
2495
Error (Jkind.Violation. of_ ~jkind_of_type
2441
2496
(Not_a_subjkind (ty's_jkind, jkind, sub_failure_reasons)))
2442
2497
in
2443
- loop ~fuel: 100 ~expanded: false ty (estimate_type_jkind env ty) jkind
2498
+ loop ~fuel: 100 ~expanded: false ty ~is_open: false
2499
+ (estimate_type_jkind env ty) jkind
2444
2500
2445
2501
let type_sort ~why ~fixed env ty =
2446
2502
let jkind, sort = Jkind. of_new_sort_var ~why in
0 commit comments