Skip to content

Commit

Permalink
support coercing string to elgible untagged variants
Browse files Browse the repository at this point in the history
  • Loading branch information
zth committed Oct 19, 2023
1 parent 761adc2 commit 3ee079d
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

We've found a bug for you!
/.../fixtures/variant_coercion_string_to_variant_no_payload.res:6:10-15

4 │ let x = "one"
5 │
6 │ let y = (x :> x)
7 │

Type string is not a subtype of x
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@unboxed
type x = One | Two

let x = "one"

let y = (x :> x)
19 changes: 19 additions & 0 deletions jscomp/ml/ctype.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3951,6 +3951,25 @@ let rec subtype_rec env trace t1 t2 cstrs =
end
| (Tconstr(p1, _, _), _) when generic_private_abbrev env p1 ->
subtype_rec env trace (expand_abbrev_opt env t1) t2 cstrs
| (Tconstr(path, [], _), Tconstr(_, [], _)) when Path.same path Predef.path_string &&
extract_concrete_typedecl env t2 |> Variant_coercion.can_try_coerce_variant_to_primitive |> Option.is_some
->
(* type coercion for strings to elgible unboxed variants:
- must be unboxed
- must coercable to string
- must have a constructor case with a string payload *)
(match Variant_coercion.can_try_coerce_variant_to_primitive (extract_concrete_typedecl env t2) with
| Some (constructors, true) ->
if constructors |> Variant_coercion.can_coerce_variant ~path ~unboxed:true
&& constructors |> List.exists(fun (c: constructor_declaration) ->
match c.cd_args with
| Cstr_tuple [{desc=Tconstr (p, [], _)}] when Path.same p Predef.path_string -> true
| _ -> false)
then
cstrs
else
(trace, t1, t2, !univar_pairs)::cstrs
| _ -> (trace, t1, t2, !univar_pairs)::cstrs)
| (Tconstr(_, [], _), Tconstr(path, [], _)) when Variant_coercion.can_coerce_path path &&
extract_concrete_typedecl env t1 |> Variant_coercion.can_try_coerce_variant_to_primitive |> Option.is_some
->
Expand Down
16 changes: 14 additions & 2 deletions jscomp/test/VariantCoercion.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions jscomp/test/VariantCoercion.res
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,11 @@ module CoerceWithPayload = {
let d: float = (c :> float)
let dd: float = (cc :> float)
}

module CoerceFromStringToVariant = {
@unboxed type strings = String(string) | First | Second | Third
let a = "hello"
let aa = "First"
let b: strings = (a :> strings)
let bb: strings = (aa :> strings)
}

0 comments on commit 3ee079d

Please sign in to comment.