Skip to content

Commit 3ee079d

Browse files
committed
support coercing string to elgible untagged variants
1 parent 761adc2 commit 3ee079d

5 files changed

+57
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
We've found a bug for you!
3+
/.../fixtures/variant_coercion_string_to_variant_no_payload.res:6:10-15
4+
5+
4 │ let x = "one"
6+
5 │
7+
6 │ let y = (x :> x)
8+
7 │
9+
10+
Type string is not a subtype of x
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@unboxed
2+
type x = One | Two
3+
4+
let x = "one"
5+
6+
let y = (x :> x)

jscomp/ml/ctype.ml

+19
Original file line numberDiff line numberDiff line change
@@ -3951,6 +3951,25 @@ let rec subtype_rec env trace t1 t2 cstrs =
39513951
end
39523952
| (Tconstr(p1, _, _), _) when generic_private_abbrev env p1 ->
39533953
subtype_rec env trace (expand_abbrev_opt env t1) t2 cstrs
3954+
| (Tconstr(path, [], _), Tconstr(_, [], _)) when Path.same path Predef.path_string &&
3955+
extract_concrete_typedecl env t2 |> Variant_coercion.can_try_coerce_variant_to_primitive |> Option.is_some
3956+
->
3957+
(* type coercion for strings to elgible unboxed variants:
3958+
- must be unboxed
3959+
- must coercable to string
3960+
- must have a constructor case with a string payload *)
3961+
(match Variant_coercion.can_try_coerce_variant_to_primitive (extract_concrete_typedecl env t2) with
3962+
| Some (constructors, true) ->
3963+
if constructors |> Variant_coercion.can_coerce_variant ~path ~unboxed:true
3964+
&& constructors |> List.exists(fun (c: constructor_declaration) ->
3965+
match c.cd_args with
3966+
| Cstr_tuple [{desc=Tconstr (p, [], _)}] when Path.same p Predef.path_string -> true
3967+
| _ -> false)
3968+
then
3969+
cstrs
3970+
else
3971+
(trace, t1, t2, !univar_pairs)::cstrs
3972+
| _ -> (trace, t1, t2, !univar_pairs)::cstrs)
39543973
| (Tconstr(_, [], _), Tconstr(path, [], _)) when Variant_coercion.can_coerce_path path &&
39553974
extract_concrete_typedecl env t1 |> Variant_coercion.can_try_coerce_variant_to_primitive |> Option.is_some
39563975
->

jscomp/test/VariantCoercion.js

+14-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/test/VariantCoercion.res

+8
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,11 @@ module CoerceWithPayload = {
4444
let d: float = (c :> float)
4545
let dd: float = (cc :> float)
4646
}
47+
48+
module CoerceFromStringToVariant = {
49+
@unboxed type strings = String(string) | First | Second | Third
50+
let a = "hello"
51+
let aa = "First"
52+
let b: strings = (a :> strings)
53+
let bb: strings = (aa :> strings)
54+
}

0 commit comments

Comments
 (0)