Skip to content

Commit 3b55267

Browse files
committed
different constructor counts
1 parent 8ec217f commit 3b55267

File tree

5 files changed

+70
-1
lines changed

5 files changed

+70
-1
lines changed

compiler/ml/ctype.ml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3726,7 +3726,31 @@ let rec subtype_rec env trace t1 t2 cstrs =
37263726
| Ok () ->
37273727
let c1_len = List.length c1 in
37283728
if c1_len > List.length c2 then
3729-
(trace, t1, t2, !univar_pairs, None) :: cstrs
3729+
let c1_constructor_names =
3730+
c1 |> List.map (fun c -> c.cd_id.name)
3731+
in
3732+
let c2_constructor_names =
3733+
c2 |> List.map (fun c -> c.cd_id.name)
3734+
in
3735+
let incompatible_constructor_names =
3736+
c1_constructor_names
3737+
|> List.filter (fun name ->
3738+
not (List.mem name c2_constructor_names))
3739+
in
3740+
( trace,
3741+
t1,
3742+
t2,
3743+
!univar_pairs,
3744+
Some
3745+
(Variant_configurations_mismatch
3746+
{
3747+
left_variant_name = p1;
3748+
right_variant_name = p2;
3749+
issue =
3750+
Incompatible_constructor_count
3751+
{constructor_names = incompatible_constructor_names};
3752+
}) )
3753+
:: cstrs
37303754
else
37313755
let constructor_map = Hashtbl.create c1_len in
37323756
c2

compiler/ml/printtyp.ml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,31 @@ let print_variant_configuration_issue ppf
16121612
"@,\
16131613
@ Fix this by making sure the variants either have the exact same \
16141614
@{<info>@tag@} configuration, or no @{<info>@tag@} at all."
1615+
| Incompatible_constructor_count {constructor_names} ->
1616+
let total_constructor_count = List.length constructor_names in
1617+
let constructor_names_to_print = constructor_names |> List.take 3 in
1618+
let not_printed_constructor_count =
1619+
total_constructor_count - List.length constructor_names_to_print
1620+
in
1621+
fprintf ppf
1622+
"@ @{<info>%s@} has %i constructor%s that @{<info>%s@} does not have: "
1623+
(Path.name left_variant_name)
1624+
total_constructor_count
1625+
(if total_constructor_count = 1 then "" else "s")
1626+
(Path.name right_variant_name);
1627+
1628+
constructor_names_to_print
1629+
|> List.iteri (fun index name ->
1630+
if index = 0 then () else fprintf ppf ", ";
1631+
fprintf ppf "@{<info>%s@}" name);
1632+
if not_printed_constructor_count > 0 then
1633+
fprintf ppf " (+%i more)" not_printed_constructor_count;
1634+
1635+
fprintf ppf
1636+
"@ Therefore, it is not possible for @{<info>%s@} to represent \
1637+
@{<info>%s@}."
1638+
(Path.name right_variant_name)
1639+
(Path.name left_variant_name)
16151640

16161641
let report_subtyping_error ppf env tr1 txt1 tr2 ctx =
16171642
wrap_printing_env env (fun () ->

compiler/ml/variant_coercion.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ exception VariantConfigurationError of variant_error
176176
type variant_configuration_issue =
177177
| Unboxed_config_not_matching of {left_unboxed: bool; right_unboxed: bool}
178178
| Tag_name_not_matching of {left_tag: string option; right_tag: string option}
179+
| Incompatible_constructor_count of {constructor_names: string list}
179180

180181
let variant_configuration_can_be_coerced2 (a1 : Parsetree.attributes)
181182
(a2 : Parsetree.attributes) =
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
We've found a bug for you!
3+
/.../fixtures/variant_to_variant_different_constructor_counts.res:6:10-15
4+
5+
4 │ let x: x = One(true)
6+
5 │
7+
6 │ let y = (x :> y)
8+
7 │
9+
10+
Type x is not a subtype of y
11+
12+
x has 4 constructors that y does not have: Two, Three, Four (+1 more)
13+
Therefore, it is not possible for y to represent x.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
type x = One(bool) | Two | Three | Four | Five
2+
type y = One(bool)
3+
4+
let x: x = One(true)
5+
6+
let y = (x :> y)

0 commit comments

Comments
 (0)