Description
The following currently causes a stack overflow in dotty (it's rejected by scalac):
trait A { type L[X] }
trait B { type L }
trait C { type M <: A }
trait D { type M >: B }
object Test {
def test(x: C with D): Unit = {
def f(y: x.M)(z: y.L[y.L]) = z
f(new B { type L[F[_]] = F[F] })(1)
}
}
The overflow is caused by the compiler attempting to evaluate the non-terminating type expression y.L[y.L]
which is ill-kinded.
The type definition type L[F[_]] = F[F] }
is clearly ill-kinded already and scalac actually reports this.
But the deeper issue is in the line above that definition: the type y.L
has two conflicting kinds, it is both a type operator and a proper type. This is because L
is declared as a type operator in trait A
and as a proper type in trait B
, which are the upper and lower bounds of x.M
, respectively. So we can construct an instance y
of B
where y.L
is a proper type and then apply it to some other type by up-casting y
to x.M
. Here's a variant of the example which illustrates that point more clearly:
//...
object Test {
def test(x: C with D): Unit = {
def f(y: x.M)(z: y.L[Any]) = z // <-- y.L used as a type operator
f(new B { type L = Any })(1) // <-- y.L defined as a proper type
}
}
It is rejected with the rather absurd error message
-- [E007] Type Mismatch Error:
9 | f(new B { type L = Any })(1)
| ^
| found: Int(1)
| required: Any[Any]
Changing the type of z
to y.L
results instead in
-- [E055] Syntax Error:
8 | def f(y: x.M)(z: y.L) = z
| ^^^
| missing type parameter for y.L
This is another instance of a know problem about type members with absurd bounds (see also issue #50): evaluation is unsafe in a context containing variables/values (here x
) of a type (here C & D
) containing type members with absurd bounds (here x.M
). In this particular case, the unsafe evaluation happens in an open type (namely y.L[Any]
) rather than an open term, and at compile time (rather than at runtime).
Clarification: by "open type" I mean a type that contains free type or term variables (as opposed to a closed type which contains no free variables).