···268268 (Xavier Leroy, report by Github user quakerquickoats, review by
269269 Jeremie Dimino)
270270271271+- #10294, #10295: fix an assert-failure in pattern-matching compilation
272272+ (Gabriel Scherer, report by Nicolás Ojeda Bär)
273273+271274- #10147, #10148: Fix building runtime with GCC on macOS.
272275 (David Allsopp, report by John Skaller)
273276
+45
testsuite/tests/basic-more/pr10294.ml
···11+(* TEST *)
22+33+type import_error = Node of string
44+type export_error = Variant of string * string
55+66+exception Import of import_error
77+exception Export of export_error
88+(* Pattern-matching analysis and compilation considers that two
99+ exceptions constructors may be equal (one may be a rebinding of
1010+ the other) as long as they have the same arity, as is the case
1111+ here.
1212+1313+ The result of splitting on these two exception constructors is what
1414+ we call an "incoherent row", a pattern matrix whose rows have
1515+ incompatible types (one matching on [import_error], the other on
1616+ [export_error]).
1717+1818+ In the case of the code below, the incoherent row is as follows:
1919+2020+ (Node _)
2121+ (Variant (_, _))
2222+2323+ Note that the two constructors [Node] and [Variant] have different
2424+ arities, but the same tag (0).
2525+2626+ In bug #10924, this causes an assertion-failure in the
2727+ pattern-matching compiler, because a matrix-decomposition
2828+ computation in Default_environment ends up considering that Node
2929+ and Variant are equal, creating a sub-matrix with one wildcard
3030+ pattern in the first row, and two in the second.
3131+3232+ This is fixed by comparing constructors by more than their tags
3333+ (which is insufficient for incoherent rows).
3434+*)
3535+let f = function
3636+ | Import (Node _) ->
3737+ 1
3838+ | Export (Variant (_, _)) ->
3939+ 2
4040+ | _ ->
4141+ 3
4242+4343+let () =
4444+ assert (f (Import (Node "foo")) = 1);
4545+ assert (f (Export (Variant ("foo", "bar"))) = 2);
testsuite/tests/basic-more/pr10294.reference
This is a binary file and will not be displayed.
+8-3
typing/types.ml
···440440 Path.same path1 path2 && b1 = b2
441441 | (Cstr_constant _|Cstr_block _|Cstr_unboxed|Cstr_extension _), _ -> false
442442443443-let may_equal_constr c1 c2 = match c1.cstr_tag,c2.cstr_tag with
444444-| Cstr_extension _,Cstr_extension _ -> c1.cstr_arity = c2.cstr_arity
445445-| tag1,tag2 -> equal_tag tag1 tag2
443443+let may_equal_constr c1 c2 =
444444+ c1.cstr_arity = c2.cstr_arity
445445+ && (match c1.cstr_tag,c2.cstr_tag with
446446+ | Cstr_extension _,Cstr_extension _ ->
447447+ (* extension constructors may be rebindings of each other *)
448448+ true
449449+ | tag1, tag2 ->
450450+ equal_tag tag1 tag2)
446451447452type label_description =
448453 { lbl_name: string; (* Short name *)