Given the following example code:
trait Gen[T, +R] {
def follow[K](gen: Gen[R, K]): Gen[T, K]
def i: T
def j: R
}
case class GenImpl[T, R](i: T, j: R) extends Gen[T, R] {
override def follow[K](gen: Gen[R, K]): Gen[T, K] = {
GenImpl[T, K](this.i, gen.j)
}
}
The compiler will give the following error:
Error:(9, 17) covariant type R occurs in invariant position in type Gen[R,K] of value gen
def follow[K](gen: Gen[R, K]): Gen[T, K]
^
however, this code cannot possibly fail a type validation in runtime. The covariant of R simply means if:
R1 <: R, R2 <: R
Then:
Gen[T, R1] <:< Gen[T, R]
So a Gen[R, K] can be a parameter of .follow() of both Gen[T, R] and Gen[T, R1]. But Gen[R1, K] can only be a parameter of .follow() of Gen[T, R1], if applied on Gen[T, R2] or Gen[T, R] it will trigger a compilation error. There is no need to set R or R1 in Gen[R/R1, K] to be contravariant to do its job.
I can't see a case that can pass compilation and fail in runtime. What do you think? Is the compiler throwing a false alarm?