Skip to content

Commit ef59ae4

Browse files
committed
variant configuration errors
1 parent 8668aec commit ef59ae4

File tree

6 files changed

+118
-13
lines changed

6 files changed

+118
-13
lines changed

compiler/ml/ctype.ml

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ type subtype_context =
8383
variant_name: Path.t;
8484
issues: Variant_coercion.variant_runtime_representation_issue list;
8585
}
86+
| Variant_configurations_mismatch of {
87+
left_variant_name: Path.t;
88+
right_variant_name: Path.t;
89+
issue: Variant_coercion.variant_configuration_issue;
90+
}
8691

8792
exception
8893
Subtype of
@@ -3587,7 +3592,9 @@ let rec subtype_rec env trace t1 t2 cstrs =
35873592
when Asttypes.Noloc.same_arg_label l1 l2 ->
35883593
let cstrs = subtype_rec env ((t2, t1) :: trace) t2 t1 cstrs in
35893594
subtype_rec env ((u1, u2) :: trace) u1 u2 cstrs
3590-
| Ttuple tl1, Ttuple tl2 -> subtype_list env trace tl1 tl2 cstrs
3595+
| Ttuple tl1, Ttuple tl2 ->
3596+
(* TODO(subtype-errors) Tuple as context *)
3597+
subtype_list env trace tl1 tl2 cstrs
35913598
| Tconstr (p1, [], _), Tconstr (p2, [], _) when Path.same p1 p2 -> cstrs
35923599
| Tconstr (p1, _tl1, _abbrev1), _
35933600
when generic_abbrev env p1 && safe_abbrev env t1 ->
@@ -3624,6 +3631,7 @@ let rec subtype_rec env trace t1 t2 cstrs =
36243631
subtype_rec env trace (expand_abbrev_opt env t1) t2 cstrs
36253632
| Tconstr (p1, [], _), Tconstr (p2, [], _)
36263633
when Path.same p1 Predef.path_int && Path.same p2 Predef.path_float ->
3634+
(* Int can always be coerced to float *)
36273635
cstrs
36283636
| Tconstr (path, [], _), Tconstr (_, [], _)
36293637
when Variant_coercion.can_coerce_primitive path
@@ -3699,15 +3707,23 @@ let rec subtype_rec env trace t1 t2 cstrs =
36993707
match
37003708
(extract_concrete_typedecl env t1, extract_concrete_typedecl env t2)
37013709
with
3702-
| ( (_, _, {type_kind = Type_variant c1; type_attributes = t1attrs}),
3703-
(_, _, {type_kind = Type_variant c2; type_attributes = t2attrs}) )
3704-
->
3705-
if
3706-
Variant_coercion.variant_configuration_can_be_coerced t1attrs
3710+
| ( (p1, _, {type_kind = Type_variant c1; type_attributes = t1attrs}),
3711+
(p2, _, {type_kind = Type_variant c2; type_attributes = t2attrs}) )
3712+
-> (
3713+
match
3714+
Variant_coercion.variant_configuration_can_be_coerced2 t1attrs
37073715
t2attrs
3708-
= false
3709-
then (trace, t1, t2, !univar_pairs, None) :: cstrs
3710-
else
3716+
with
3717+
| Error issue ->
3718+
( trace,
3719+
t1,
3720+
t2,
3721+
!univar_pairs,
3722+
Some
3723+
(Variant_configurations_mismatch
3724+
{left_variant_name = p1; right_variant_name = p2; issue}) )
3725+
:: cstrs
3726+
| Ok () ->
37113727
let c1_len = List.length c1 in
37123728
if c1_len > List.length c2 then
37133729
(trace, t1, t2, !univar_pairs, None) :: cstrs
@@ -3767,7 +3783,7 @@ let rec subtype_rec env trace t1 t2 cstrs =
37673783
else false
37683784
| _ -> false)
37693785
then cstrs
3770-
else (trace, t1, t2, !univar_pairs, None) :: cstrs
3786+
else (trace, t1, t2, !univar_pairs, None) :: cstrs)
37713787
| ( (_, _, {type_kind = Type_record (fields1, repr1)}),
37723788
(_, _, {type_kind = Type_record (fields2, repr2)}) ) ->
37733789
let same_repr =

compiler/ml/ctype.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ type subtype_context =
3232
variant_name: Path.t;
3333
issues: Variant_coercion.variant_runtime_representation_issue list;
3434
}
35+
| Variant_configurations_mismatch of {
36+
left_variant_name: Path.t;
37+
right_variant_name: Path.t;
38+
issue: Variant_coercion.variant_configuration_issue;
39+
}
3540

3641
exception Unify of (type_expr * type_expr) list
3742
exception Tags of label * label

compiler/ml/printtyp.ml

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,43 @@ let print_variant_runtime_representation_issue ppf variant_name
15761576
a runtime representation of @{<info>%s@}."
15771577
(Path.name variant_name)
15781578
(Path.name expected_typename)
1579+
1580+
let print_variant_configuration_issue ppf
1581+
(issue : Variant_coercion.variant_configuration_issue) ~left_variant_name
1582+
~right_variant_name =
1583+
match issue with
1584+
| Unboxed_config_not_matching {left_unboxed; right_unboxed} ->
1585+
fprintf ppf
1586+
"@ The variants have different @{<info>@unboxed@} configurations.";
1587+
let print_unboxed_status ppf unboxed name =
1588+
fprintf ppf "@ - Variant @{<info>%s@} is @{<error>%s@}unboxed."
1589+
(Path.name name)
1590+
(if unboxed then "not " else "")
1591+
in
1592+
print_unboxed_status ppf left_unboxed left_variant_name;
1593+
print_unboxed_status ppf right_unboxed right_variant_name;
1594+
fprintf ppf
1595+
"@,\
1596+
@ Fix this by making sure the variants either both have, or don't have, \
1597+
the @{<info>@unboxed@} attribute."
1598+
| Tag_name_not_matching {left_tag; right_tag} ->
1599+
fprintf ppf "@ The variants have different @{<info>@tag@} configurations.";
1600+
let print_tag ppf tag variant_name =
1601+
match tag with
1602+
| Some tag ->
1603+
fprintf ppf "@ - @{<info>%s@} has tag @{<info>%s@}."
1604+
(Path.name variant_name) tag
1605+
| None ->
1606+
fprintf ppf "@ - @{<info>%s@} has no explicit tag."
1607+
(Path.name variant_name)
1608+
in
1609+
print_tag ppf left_tag left_variant_name;
1610+
print_tag ppf right_tag right_variant_name;
1611+
fprintf ppf
1612+
"@,\
1613+
@ Fix this by making sure the variants either have the exact same \
1614+
@{<info>@tag@} configuration, or no @{<info>@tag@} at all."
1615+
15791616
let report_subtyping_error ppf env tr1 txt1 tr2 ctx =
15801617
wrap_printing_env env (fun () ->
15811618
reset ();
@@ -1618,7 +1655,11 @@ let report_subtyping_error ppf env tr1 txt1 tr2 ctx =
16181655
(fun issue ->
16191656
fprintf ppf "@ ";
16201657
print_variant_runtime_representation_issue ppf variant_name issue)
1621-
issues);
1658+
issues
1659+
| Variant_configurations_mismatch
1660+
{left_variant_name; right_variant_name; issue} ->
1661+
print_variant_configuration_issue ppf issue ~left_variant_name
1662+
~right_variant_name);
16221663
fprintf ppf "@]"
16231664
| None -> ())
16241665

compiler/ml/variant_coercion.ml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,37 @@ type variant_error =
173173

174174
exception VariantConfigurationError of variant_error
175175

176+
type variant_configuration_issue =
177+
| Unboxed_config_not_matching of {left_unboxed: bool; right_unboxed: bool}
178+
| Tag_name_not_matching of {left_tag: string option; right_tag: string option}
179+
180+
let variant_configuration_can_be_coerced2 (a1 : Parsetree.attributes)
181+
(a2 : Parsetree.attributes) =
182+
let unboxed =
183+
match
184+
( Ast_untagged_variants.process_untagged a1,
185+
Ast_untagged_variants.process_untagged a2 )
186+
with
187+
| true, true | false, false -> Ok ()
188+
| left, right ->
189+
Error
190+
(Unboxed_config_not_matching
191+
{left_unboxed = left; right_unboxed = right})
192+
in
193+
let tag =
194+
match
195+
( Ast_untagged_variants.process_tag_name a1,
196+
Ast_untagged_variants.process_tag_name a2 )
197+
with
198+
| Some tag1, Some tag2 when tag1 = tag2 -> Ok ()
199+
| None, None -> Ok ()
200+
| tag1, tag2 ->
201+
Error (Tag_name_not_matching {left_tag = tag1; right_tag = tag2})
202+
in
203+
match (unboxed, tag) with
204+
| Ok (), Ok () -> Ok ()
205+
| Error e, _ | _, Error e -> Error e
206+
176207
let variant_configuration_can_be_coerced (a1 : Parsetree.attributes)
177208
(a2 : Parsetree.attributes) =
178209
let unboxed =

tests/build_tests/super_errors/expected/variant_to_variant_coercion_tag.res.expected

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,10 @@
77
6 │ let y = (x :> y)
88
7 │
99

10-
Type x is not a subtype of y
10+
Type x is not a subtype of y
11+
12+
The variants have different @tag configurations.
13+
- x has tag kind.
14+
- y has no explicit tag.
15+
16+
Fix this by making sure the variants either have the exact same @tag configuration, or no @tag at all.

tests/build_tests/super_errors/expected/variant_to_variant_coercion_unboxed.res.expected

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,10 @@
77
6 │ let y = (x :> y)
88
7 │
99

10-
Type x is not a subtype of y
10+
Type x is not a subtype of y
11+
12+
The variants have different @unboxed configurations.
13+
- Variant x is not unboxed.
14+
- Variant y is unboxed.
15+
16+
Fix this by making sure the variants either both have, or don't have, the @unboxed attribute.

0 commit comments

Comments
 (0)