Skip to content

Commit

Permalink
Fix HK type param bounds variance checking
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed Nov 11, 2024
1 parent d78516a commit 49962b2
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 1 deletion.
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/printing/Formatting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ object Formatting {
def show(x: H *: T) =
CtxShow(toStr(x.head) *: toShown(x.tail).asInstanceOf[Tuple])

given Show[typer.VarianceChecker.VarianceError] with
def show(x: typer.VarianceChecker.VarianceError) =
CtxShow("VarianceError(" + toStr(x.tvar) + ", " + toStr(x.required) + ")")

given Show[FlagSet] with
def show(x: FlagSet) = x.flagsString

Expand Down
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class VarianceChecker(using Context) {
* explicitly (their TypeDefs will be passed here.) For MethodTypes, the
* same is true of the parameters (ValDefs).
*/
def apply(status: Option[VarianceError], tp: Type): Option[VarianceError] = trace(s"variance checking $tp of $base at $variance", variances) {
def apply(status: Option[VarianceError], tp: Type): Option[VarianceError] = trace(i"variance checking $tp of $base at $variance", variances) {
try
if (status.isDefined) status
else tp match {
Expand All @@ -136,6 +136,14 @@ class VarianceChecker(using Context) {
status
case tp: ClassInfo =>
foldOver(status, tp.parents)
case tp @ TypeBounds(lo: LambdaType, hi) if lo ne hi =>
// When checking the info of higher-kinded type members,
// (such as the following from i21625)
// type F_NL_LB[M <: L] >: LB[M]
// we only check the lambda type param bounds (`>: L`)
// when checking the upper bound, eg `<: [M <: L] =>> Any`,
// not when checking the lower bound `>: [M <: L] =>> LB[M]`.
foldOver(status, tp.derivedTypeBounds(lo.resultType, hi))
case _ =>
foldOver(status, tp)
}
Expand Down
72 changes: 72 additions & 0 deletions tests/neg/i21625.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
-- Error: tests/neg/i21625.scala:5:7 -----------------------------------------------------------------------------------
5 | type F_LA_LB[K >: L] >: LB[K] // error: >: L
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| contravariant type L occurs in covariant position in type [K >: L] >: LB[K] of type F_LA_LB
-- Error: tests/neg/i21625.scala:8:7 -----------------------------------------------------------------------------------
8 | type F_NU_LB[V <: U] >: LB[V] // error: <: U
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| covariant type U occurs in contravariant position in type [V <: U] >: LB[V] of type F_NU_LB
-- Error: tests/neg/i21625.scala:10:7 ----------------------------------------------------------------------------------
10 | type F_LA_UB[K >: L] <: UB[K] // error: >: L
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| contravariant type L occurs in covariant position in type [K >: L] <: UB[K] of type F_LA_UB
-- Error: tests/neg/i21625.scala:13:7 ----------------------------------------------------------------------------------
13 | type F_NU_UB[V <: U] <: UB[V] // error: <: U
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| covariant type U occurs in contravariant position in type [V <: U] <: UB[V] of type F_NU_UB
-- Error: tests/neg/i21625.scala:17:7 ----------------------------------------------------------------------------------
17 | F_NL_LB[M <: L] >: LB[M], // error: <: L
| ^^^^^^^^^^^^^^^^^^^^^^^^
| contravariant type L occurs in covariant position in type [M <: L] >: LB[M] of type F_NL_LB
-- Error: tests/neg/i21625.scala:18:7 ----------------------------------------------------------------------------------
18 | F_UA_LB[T >: U] >: LB[T], // error: >: U
| ^^^^^^^^^^^^^^^^^^^^^^^^
| covariant type U occurs in contravariant position in type [T >: U] >: LB[T] of type F_UA_LB
-- Error: tests/neg/i21625.scala:22:7 ----------------------------------------------------------------------------------
22 | F_NL_UB[M <: L] <: UB[M], // error: <: L
| ^^^^^^^^^^^^^^^^^^^^^^^^
| contravariant type L occurs in covariant position in type [M <: L] <: UB[M] of type F_NL_UB
-- Error: tests/neg/i21625.scala:23:7 ----------------------------------------------------------------------------------
23 | F_UA_UB[T >: U] <: UB[T], // error: >: U
| ^^^^^^^^^^^^^^^^^^^^^^^^
| covariant type U occurs in contravariant position in type [T >: U] <: UB[T] of type F_UA_UB
-- Error: tests/neg/i21625.scala:28:7 ----------------------------------------------------------------------------------
28 | type M <: L // error: <: L
| ^^^^^^^^^^^
| contravariant type L occurs in covariant position in type <: L of type M
-- Error: tests/neg/i21625.scala:29:7 ----------------------------------------------------------------------------------
29 | type T >: U // error: >: U
| ^^^^^^^^^^^
| covariant type U occurs in contravariant position in type >: U of type T
-- Error: tests/neg/i21625.scala:32:10 ---------------------------------------------------------------------------------
32 | def d_K[K >: L](): K // error: >: L
| ^^^^^^
| contravariant type L occurs in covariant position in type >: L of type K
-- Error: tests/neg/i21625.scala:33:6 ----------------------------------------------------------------------------------
33 | def d_L(): L // error: => L
| ^^^^^^^^^^^^^^^^^^^^
| contravariant type L occurs in covariant position in type (): L of method d_L
-- Error: tests/neg/i21625.scala:37:10 ---------------------------------------------------------------------------------
37 | def d_V[V <: U](): V // error: <: U
| ^^^^^^
| covariant type U occurs in contravariant position in type <: U of type V
-- Error: tests/neg/i21625.scala:40:6 ----------------------------------------------------------------------------------
40 | val v_L: L // error: L
| ^^^^^^^^^^
| contravariant type L occurs in covariant position in type L of value v_L
-- Error: tests/neg/i21625.scala:48:15 ---------------------------------------------------------------------------------
48 | def d_K_Unit[K >: L](): K => Unit // error: >: L
| ^^^^^^
| contravariant type L occurs in covariant position in type >: L of type K
-- Error: tests/neg/i21625.scala:52:6 ----------------------------------------------------------------------------------
52 | def d_U_Unit(): U => Unit // error: U =>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| covariant type U occurs in contravariant position in type (): U => Unit of method d_U_Unit
-- Error: tests/neg/i21625.scala:53:15 ---------------------------------------------------------------------------------
53 | def d_V_Unit[V <: U](): V => Unit // error: <: U
| ^^^^^^
| covariant type U occurs in contravariant position in type <: U of type V
-- Error: tests/neg/i21625.scala:59:6 ----------------------------------------------------------------------------------
59 | val v_U_Unit: U => Unit // error: U =>
| ^^^^^^^^^^^^^^^^^^^^^^^
| covariant type U occurs in contravariant position in type U => Unit of value v_U_Unit
60 changes: 60 additions & 0 deletions tests/neg/i21625.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
trait LB[X]; trait UB[Y]

trait Foo[-L, +U]:

type F_LA_LB[K >: L] >: LB[K] // error: >: L
type F_NL_LB[M <: L] >: LB[M] // was: error: <: L
type F_UA_LB[T >: U] >: LB[T] // was: error: >: U
type F_NU_LB[V <: U] >: LB[V] // error: <: U

type F_LA_UB[K >: L] <: UB[K] // error: >: L
type F_NL_UB[M <: L] <: UB[M]
type F_UA_UB[T >: U] <: UB[T]
type F_NU_UB[V <: U] <: UB[V] // error: <: U

def hk[
F_LA_LB[K >: L] >: LB[K], // was: error: >: L
F_NL_LB[M <: L] >: LB[M], // error: <: L
F_UA_LB[T >: U] >: LB[T], // error: >: U
F_NU_LB[V <: U] >: LB[V], // was: error: <: U

F_LA_UB[K >: L] <: UB[K],
F_NL_UB[M <: L] <: UB[M], // error: <: L
F_UA_UB[T >: U] <: UB[T], // error: >: U
F_NU_UB[V <: U] <: UB[V],
]: Unit

type K >: L
type M <: L // error: <: L
type T >: U // error: >: U
type V <: U

def d_K[K >: L](): K // error: >: L
def d_L(): L // error: => L
def d_M[M <: L](): M
def d_T[T >: U](): T
def d_U(): U
def d_V[V <: U](): V // error: <: U

val v_K: K
val v_L: L // error: L
val v_M: M // indirect error: M <: L
val v_T: T // indirect error: T >: U
val v_U: U
val v_V: V

// reverse

def d_K_Unit[K >: L](): K => Unit // error: >: L
def d_L_Unit(): L => Unit
def d_M_Unit[M <: L](): M => Unit
def d_T_Unit[T >: U](): T => Unit
def d_U_Unit(): U => Unit // error: U =>
def d_V_Unit[V <: U](): V => Unit // error: <: U

val v_K_Unit: K => Unit
val v_L_Unit: L => Unit
val v_M_Unit: M => Unit
val v_T_Unit: T => Unit
val v_U_Unit: U => Unit // error: U =>
val v_V_Unit: V => Unit

0 comments on commit 49962b2

Please sign in to comment.