Skip to content

Commit d0992b7

Browse files
committed
Fix variance composition (#12623)
Possible positive occurrence under possible negative occurrence were forgotten, making the typechecker accepts the absurd statement type -'a n type +'a p type +'a ko = 'a p n (cherry picked from commit 1a9c453)
1 parent c23c68b commit d0992b7

File tree

5 files changed

+96
-1
lines changed

5 files changed

+96
-1
lines changed

Changes

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
OCaml 5.1.1
2+
-----------
3+
4+
### Bug fixes:
5+
6+
- #12623, fix the computation of variance composition
7+
(Florian Angeletti, report by Vesa Karvonen, review by Gabriel Scherer)
8+
19
OCaml 5.1.0 (14 September 2023)
210
-------------------------------
311

boot/ocamlc

-2 Bytes
Binary file not shown.

boot/ocamllex

-2 Bytes
Binary file not shown.

testsuite/tests/typing-misc/variance.ml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,90 @@ type !'a t = (module s with type t = 'a);;
3636
module type s = sig type t end
3737
type 'a t = (module s with type t = 'a)
3838
|}]
39+
40+
(* Composition *)
41+
type -'a n
42+
type +'a p
43+
type !'a i
44+
45+
type +'a error_np = 'a n p;;
46+
[%%expect{|
47+
type -'a n
48+
type +'a p
49+
type !'a i
50+
Line 5, characters 0-26:
51+
5 | type +'a error_np = 'a n p;;
52+
^^^^^^^^^^^^^^^^^^^^^^^^^^
53+
Error: In this definition, expected parameter variances are not satisfied.
54+
The 1st type parameter was expected to be covariant,
55+
but it is contravariant.
56+
|}]
57+
58+
59+
type +'a error_pn = 'a p n;;
60+
[%%expect{|
61+
Line 1, characters 0-26:
62+
1 | type +'a error_pn = 'a p n;;
63+
^^^^^^^^^^^^^^^^^^^^^^^^^^
64+
Error: In this definition, expected parameter variances are not satisfied.
65+
The 1st type parameter was expected to be covariant,
66+
but it is contravariant.
67+
|}]
68+
69+
type -'a error_pp = 'a p p;;
70+
[%%expect{|
71+
Line 1, characters 0-26:
72+
1 | type -'a error_pp = 'a p p;;
73+
^^^^^^^^^^^^^^^^^^^^^^^^^^
74+
Error: In this definition, expected parameter variances are not satisfied.
75+
The 1st type parameter was expected to be contravariant,
76+
but it is covariant.
77+
|}]
78+
79+
type -'a error_nn = 'a n n;;
80+
[%%expect{|
81+
Line 1, characters 0-26:
82+
1 | type -'a error_nn = 'a n n;;
83+
^^^^^^^^^^^^^^^^^^^^^^^^^^
84+
Error: In this definition, expected parameter variances are not satisfied.
85+
The 1st type parameter was expected to be contravariant,
86+
but it is covariant.
87+
|}]
88+
89+
type !'a inj_in = 'a i n
90+
[%%expect{|
91+
Line 1, characters 0-24:
92+
1 | type !'a inj_in = 'a i n
93+
^^^^^^^^^^^^^^^^^^^^^^^^
94+
Error: In this definition, expected parameter variances are not satisfied.
95+
The 1st type parameter was expected to be injective invariant,
96+
but it is invariant.
97+
|}]
98+
99+
type !'a inj_in = 'a n i
100+
[%%expect{|
101+
Line 1, characters 0-24:
102+
1 | type !'a inj_in = 'a n i
103+
^^^^^^^^^^^^^^^^^^^^^^^^
104+
Error: In this definition, expected parameter variances are not satisfied.
105+
The 1st type parameter was expected to be injective invariant,
106+
but it is invariant.
107+
|}]
108+
109+
module Make_covariant(M: sig type 'a t end): sig
110+
type 'a i = 'a
111+
type +'a t = 'a i M.t
112+
end = struct
113+
type 'a i = 'a
114+
type +'a t = 'a i M.t
115+
end
116+
117+
module Positive_ref = Make_covariant(struct type 'a t = 'a ref end)
118+
[%%expect {|
119+
Line 6, characters 2-23:
120+
6 | type +'a t = 'a i M.t
121+
^^^^^^^^^^^^^^^^^^^^^
122+
Error: In this definition, expected parameter variances are not satisfied.
123+
The 1st type parameter was expected to be covariant,
124+
but it is invariant.
125+
|}]

typing/types.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ module Variance = struct
186186
let mp =
187187
mem May_pos v1 && mem May_pos v2 || mem May_neg v1 && mem May_neg v2
188188
and mn =
189-
mem May_pos v1 && mem May_neg v2 || mem May_pos v1 && mem May_neg v2
189+
mem May_pos v1 && mem May_neg v2 || mem May_neg v1 && mem May_pos v2
190190
and mw = mem May_weak v1 && v2 <> null || v1 <> null && mem May_weak v2
191191
and inj = mem Inj v1 && mem Inj v2
192192
and pos = mem Pos v1 && mem Pos v2 || mem Neg v1 && mem Neg v2

0 commit comments

Comments
 (0)