Skip to content

Commit 3c8cd67

Browse files
committed
allow coercing unboxed with payload to primitive when applicable
1 parent 776e24d commit 3c8cd67

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

jscomp/ml/ctype.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3956,8 +3956,8 @@ let rec subtype_rec env trace t1 t2 cstrs =
39563956
->
39573957
(* type coercion for variants to primitives *)
39583958
(match Variant_coercion.can_try_coerce_variant_to_primitive (extract_concrete_typedecl env t1) with
3959-
| Some constructors ->
3960-
if constructors |> Variant_coercion.can_coerce_variant ~path then
3959+
| Some (constructors, unboxed) ->
3960+
if constructors |> Variant_coercion.can_coerce_variant ~path ~unboxed then
39613961
cstrs
39623962
else
39633963
(trace, t1, t2, !univar_pairs)::cstrs

jscomp/ml/variant_coercion.ml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,28 @@ let can_coerce_path (path : Path.t) =
66
|| Path.same path Predef.path_int
77
|| Path.same path Predef.path_float
88

9-
let can_coerce_variant ~(path : Path.t)
9+
let check_paths_same p1 p2 target_path =
10+
Path.same p1 target_path && Path.same p2 target_path
11+
12+
let can_coerce_variant ~(path : Path.t) ~unboxed
1013
(constructors : Types.constructor_declaration list) =
1114
constructors
1215
|> List.for_all (fun (c : Types.constructor_declaration) ->
1316
let args = c.cd_args in
14-
let payload = Ast_untagged_variants.process_tag_type c.cd_attributes in
17+
let asPayload =
18+
Ast_untagged_variants.process_tag_type c.cd_attributes
19+
in
1520
match args with
21+
| Cstr_tuple [{desc = Tconstr (p, [], _)}] when unboxed ->
22+
let path_same = check_paths_same p path in
23+
(* unboxed String(string) :> string *)
24+
path_same Predef.path_string
25+
|| (* unboxed Number(float) :> float *)
26+
path_same Predef.path_float
1627
| Cstr_tuple [] -> (
17-
match payload with
28+
(* Check that @as payloads match with the target path to coerce to.
29+
No @as means the default encoding, which is string *)
30+
match asPayload with
1831
| None | Some (String _) -> Path.same path Predef.path_string
1932
| Some (Int _) -> Path.same path Predef.path_int
2033
| Some (Float _) -> Path.same path Predef.path_float
@@ -24,10 +37,10 @@ let can_coerce_variant ~(path : Path.t)
2437
let can_try_coerce_variant_to_primitive
2538
((_, p, typedecl) : Path.t * Path.t * Types.type_declaration) =
2639
match typedecl with
27-
| {type_kind = Type_variant constructors; type_params = []}
40+
| {type_kind = Type_variant constructors; type_params = []; type_attributes}
2841
when Path.name p <> "bool" ->
2942
(* bool is represented as a variant internally, so we need to account for that *)
30-
Some constructors
43+
Some (constructors, type_attributes |> Ast_untagged_variants.has_untagged)
3144
| _ -> None
3245

3346
let variant_representation_matches (c1_attrs : Parsetree.attributes)

0 commit comments

Comments
 (0)