Consider the following snippet:
trait X[-T]
object Y extends X[Nothing]
def a[T](x: X[T]): X[T] = x
a(Y)
Compilation of the above (2.12.3) fails with:
type mismatch;
found : Y.type
required: X[T]
a(Y)
^
This compiles fine if:
Nothing
is used (e.g. object Y extends X[String]
)a
doesn't use T
in its return type (e.g. def a[T](x: X[T]): Unit = {}
)a
is explicitly given (i.e. a[Nothing](Y)
)T
is covariant, not contravariant (also fails if it's invariant)Is this some special case in the compiler for Nothing
?
As an "interesting" work-around, the following seems to work fine:
trait X[-T]
object Y extends X[Nothing]
def a[T, U <: T](x: X[T]): X[U] = x
a(Y)
I will try to explain the code line by line
Line 1: trait X[-T]
-> trait X is contravariant in type T. So you can replace any variable of type X[T] with its subtype. In case of contravariant types, Z[A] is subtype of Z[B] if B is subtype of A.
Line 2: object Y extends X[Nothing]
-> object Y is of type X[Nothing]. Please note that Nothing is subtype of all other types.
Line 3: def a[T](x: X[T]): X[T] = x
-> define an expression which takes arguments of type X[T]. Because trait X is contravariant in type T, you can also pass subtypes of X[T] i.e. X[N] such that T is subtype of N
Line 4: a(Y)
-> Call expression 'a' with argument of type X[Nothing]. Since the compiler does not know the type of argument of 'a', it can not decide if X[Nothing] is subtype of X[T]. There are multiple ways to resolve this
Solution 1: `a[Nothing]` -> explicitly defining the type
Solution 2: `tait X[+T]` -> make X covariant in type T. In this case Z[A] is subtype of Z[B] if A is subtype of B. This will work because Nothing is subtype of any other type
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With