Skip to content

Commit 49962b2

Browse files
committed
Fix HK type param bounds variance checking
1 parent d78516a commit 49962b2

File tree

4 files changed

+145
-1
lines changed

4 files changed

+145
-1
lines changed

compiler/src/dotty/tools/dotc/printing/Formatting.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ object Formatting {
8787
def show(x: H *: T) =
8888
CtxShow(toStr(x.head) *: toShown(x.tail).asInstanceOf[Tuple])
8989

90+
given Show[typer.VarianceChecker.VarianceError] with
91+
def show(x: typer.VarianceChecker.VarianceError) =
92+
CtxShow("VarianceError(" + toStr(x.tvar) + ", " + toStr(x.required) + ")")
93+
9094
given Show[FlagSet] with
9195
def show(x: FlagSet) = x.flagsString
9296

compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class VarianceChecker(using Context) {
120120
* explicitly (their TypeDefs will be passed here.) For MethodTypes, the
121121
* same is true of the parameters (ValDefs).
122122
*/
123-
def apply(status: Option[VarianceError], tp: Type): Option[VarianceError] = trace(s"variance checking $tp of $base at $variance", variances) {
123+
def apply(status: Option[VarianceError], tp: Type): Option[VarianceError] = trace(i"variance checking $tp of $base at $variance", variances) {
124124
try
125125
if (status.isDefined) status
126126
else tp match {
@@ -136,6 +136,14 @@ class VarianceChecker(using Context) {
136136
status
137137
case tp: ClassInfo =>
138138
foldOver(status, tp.parents)
139+
case tp @ TypeBounds(lo: LambdaType, hi) if lo ne hi =>
140+
// When checking the info of higher-kinded type members,
141+
// (such as the following from i21625)
142+
// type F_NL_LB[M <: L] >: LB[M]
143+
// we only check the lambda type param bounds (`>: L`)
144+
// when checking the upper bound, eg `<: [M <: L] =>> Any`,
145+
// not when checking the lower bound `>: [M <: L] =>> LB[M]`.
146+
foldOver(status, tp.derivedTypeBounds(lo.resultType, hi))
139147
case _ =>
140148
foldOver(status, tp)
141149
}

tests/neg/i21625.check

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
-- Error: tests/neg/i21625.scala:5:7 -----------------------------------------------------------------------------------
2+
5 | type F_LA_LB[K >: L] >: LB[K] // error: >: L
3+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
| contravariant type L occurs in covariant position in type [K >: L] >: LB[K] of type F_LA_LB
5+
-- Error: tests/neg/i21625.scala:8:7 -----------------------------------------------------------------------------------
6+
8 | type F_NU_LB[V <: U] >: LB[V] // error: <: U
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8+
| covariant type U occurs in contravariant position in type [V <: U] >: LB[V] of type F_NU_LB
9+
-- Error: tests/neg/i21625.scala:10:7 ----------------------------------------------------------------------------------
10+
10 | type F_LA_UB[K >: L] <: UB[K] // error: >: L
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
| contravariant type L occurs in covariant position in type [K >: L] <: UB[K] of type F_LA_UB
13+
-- Error: tests/neg/i21625.scala:13:7 ----------------------------------------------------------------------------------
14+
13 | type F_NU_UB[V <: U] <: UB[V] // error: <: U
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
| covariant type U occurs in contravariant position in type [V <: U] <: UB[V] of type F_NU_UB
17+
-- Error: tests/neg/i21625.scala:17:7 ----------------------------------------------------------------------------------
18+
17 | F_NL_LB[M <: L] >: LB[M], // error: <: L
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^
20+
| contravariant type L occurs in covariant position in type [M <: L] >: LB[M] of type F_NL_LB
21+
-- Error: tests/neg/i21625.scala:18:7 ----------------------------------------------------------------------------------
22+
18 | F_UA_LB[T >: U] >: LB[T], // error: >: U
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^
24+
| covariant type U occurs in contravariant position in type [T >: U] >: LB[T] of type F_UA_LB
25+
-- Error: tests/neg/i21625.scala:22:7 ----------------------------------------------------------------------------------
26+
22 | F_NL_UB[M <: L] <: UB[M], // error: <: L
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^
28+
| contravariant type L occurs in covariant position in type [M <: L] <: UB[M] of type F_NL_UB
29+
-- Error: tests/neg/i21625.scala:23:7 ----------------------------------------------------------------------------------
30+
23 | F_UA_UB[T >: U] <: UB[T], // error: >: U
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^
32+
| covariant type U occurs in contravariant position in type [T >: U] <: UB[T] of type F_UA_UB
33+
-- Error: tests/neg/i21625.scala:28:7 ----------------------------------------------------------------------------------
34+
28 | type M <: L // error: <: L
35+
| ^^^^^^^^^^^
36+
| contravariant type L occurs in covariant position in type <: L of type M
37+
-- Error: tests/neg/i21625.scala:29:7 ----------------------------------------------------------------------------------
38+
29 | type T >: U // error: >: U
39+
| ^^^^^^^^^^^
40+
| covariant type U occurs in contravariant position in type >: U of type T
41+
-- Error: tests/neg/i21625.scala:32:10 ---------------------------------------------------------------------------------
42+
32 | def d_K[K >: L](): K // error: >: L
43+
| ^^^^^^
44+
| contravariant type L occurs in covariant position in type >: L of type K
45+
-- Error: tests/neg/i21625.scala:33:6 ----------------------------------------------------------------------------------
46+
33 | def d_L(): L // error: => L
47+
| ^^^^^^^^^^^^^^^^^^^^
48+
| contravariant type L occurs in covariant position in type (): L of method d_L
49+
-- Error: tests/neg/i21625.scala:37:10 ---------------------------------------------------------------------------------
50+
37 | def d_V[V <: U](): V // error: <: U
51+
| ^^^^^^
52+
| covariant type U occurs in contravariant position in type <: U of type V
53+
-- Error: tests/neg/i21625.scala:40:6 ----------------------------------------------------------------------------------
54+
40 | val v_L: L // error: L
55+
| ^^^^^^^^^^
56+
| contravariant type L occurs in covariant position in type L of value v_L
57+
-- Error: tests/neg/i21625.scala:48:15 ---------------------------------------------------------------------------------
58+
48 | def d_K_Unit[K >: L](): K => Unit // error: >: L
59+
| ^^^^^^
60+
| contravariant type L occurs in covariant position in type >: L of type K
61+
-- Error: tests/neg/i21625.scala:52:6 ----------------------------------------------------------------------------------
62+
52 | def d_U_Unit(): U => Unit // error: U =>
63+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
64+
| covariant type U occurs in contravariant position in type (): U => Unit of method d_U_Unit
65+
-- Error: tests/neg/i21625.scala:53:15 ---------------------------------------------------------------------------------
66+
53 | def d_V_Unit[V <: U](): V => Unit // error: <: U
67+
| ^^^^^^
68+
| covariant type U occurs in contravariant position in type <: U of type V
69+
-- Error: tests/neg/i21625.scala:59:6 ----------------------------------------------------------------------------------
70+
59 | val v_U_Unit: U => Unit // error: U =>
71+
| ^^^^^^^^^^^^^^^^^^^^^^^
72+
| covariant type U occurs in contravariant position in type U => Unit of value v_U_Unit

tests/neg/i21625.scala

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
trait LB[X]; trait UB[Y]
2+
3+
trait Foo[-L, +U]:
4+
5+
type F_LA_LB[K >: L] >: LB[K] // error: >: L
6+
type F_NL_LB[M <: L] >: LB[M] // was: error: <: L
7+
type F_UA_LB[T >: U] >: LB[T] // was: error: >: U
8+
type F_NU_LB[V <: U] >: LB[V] // error: <: U
9+
10+
type F_LA_UB[K >: L] <: UB[K] // error: >: L
11+
type F_NL_UB[M <: L] <: UB[M]
12+
type F_UA_UB[T >: U] <: UB[T]
13+
type F_NU_UB[V <: U] <: UB[V] // error: <: U
14+
15+
def hk[
16+
F_LA_LB[K >: L] >: LB[K], // was: error: >: L
17+
F_NL_LB[M <: L] >: LB[M], // error: <: L
18+
F_UA_LB[T >: U] >: LB[T], // error: >: U
19+
F_NU_LB[V <: U] >: LB[V], // was: error: <: U
20+
21+
F_LA_UB[K >: L] <: UB[K],
22+
F_NL_UB[M <: L] <: UB[M], // error: <: L
23+
F_UA_UB[T >: U] <: UB[T], // error: >: U
24+
F_NU_UB[V <: U] <: UB[V],
25+
]: Unit
26+
27+
type K >: L
28+
type M <: L // error: <: L
29+
type T >: U // error: >: U
30+
type V <: U
31+
32+
def d_K[K >: L](): K // error: >: L
33+
def d_L(): L // error: => L
34+
def d_M[M <: L](): M
35+
def d_T[T >: U](): T
36+
def d_U(): U
37+
def d_V[V <: U](): V // error: <: U
38+
39+
val v_K: K
40+
val v_L: L // error: L
41+
val v_M: M // indirect error: M <: L
42+
val v_T: T // indirect error: T >: U
43+
val v_U: U
44+
val v_V: V
45+
46+
// reverse
47+
48+
def d_K_Unit[K >: L](): K => Unit // error: >: L
49+
def d_L_Unit(): L => Unit
50+
def d_M_Unit[M <: L](): M => Unit
51+
def d_T_Unit[T >: U](): T => Unit
52+
def d_U_Unit(): U => Unit // error: U =>
53+
def d_V_Unit[V <: U](): V => Unit // error: <: U
54+
55+
val v_K_Unit: K => Unit
56+
val v_L_Unit: L => Unit
57+
val v_M_Unit: M => Unit
58+
val v_T_Unit: T => Unit
59+
val v_U_Unit: U => Unit // error: U =>
60+
val v_V_Unit: V => Unit

0 commit comments

Comments
 (0)