无法推断逆变Nothing类型参数

ada*_*amw 10 scala scala-compiler

请考虑以下代码段:

trait X[-T]
object Y extends X[Nothing]
def a[T](x: X[T]): X[T] = x
a(Y)
Run Code Online (Sandbox Code Playgroud)

上述(2.12.3)的汇编失败了:

type mismatch;
found   : Y.type
required: X[T]
   a(Y)
     ^
Run Code Online (Sandbox Code Playgroud)

如果符合以下情况,这将编

  • 与使用的类型不同Nothing(例如object Y extends X[String])
  • 该方法a不在T其返回类型中使用(例如def a[T](x: X[T]): Unit = {})
  • a明确给出了类型参数(即a[Nothing](Y))
  • T 是协变的,而不是逆变的(如果它是不变的也会失败)

这是编译器中的一些特例Nothing吗?

作为一个"有趣"的解决方案,以下似乎工作正常:

trait X[-T]
object Y extends X[Nothing]
def a[T, U <: T](x: X[T]): X[U] = x
a(Y)
Run Code Online (Sandbox Code Playgroud)

AB9*_*9KT 1

我将尝试逐行解释代码

第 1 行:trait X[-T]-> 特征 X 在类型 T 中是逆变的。因此,您可以将类型 X[T] 的任何变量替换为其子类型。在逆变类型的情况下,如果 B 是 A 的子类型,则 Z[A] 是 Z[B] 的子类型。

第 2 行:object Y extends X[Nothing]-> 对象 Y 的类型为 X[Nothing]。请注意,Nothing 是所有其他类型的子类型。

第 3 行:def a[T](x: X[T]): X[T] = x-> 定义一个采用 X[T] 类型参数的表达式。因为特征 X 在类型 T 中是逆变的,所以您还可以传递 X[T] 的子类型,即 X[N],使得 T 是 N 的子类型

第 4 行:a(Y)-> 使用 X[Nothing] 类型的参数调用表达式“a”。由于编译器不知道“a”的参数类型,因此无法确定 X[Nothing] 是否是 X[T] 的子类型。有多种方法可以解决这个问题

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
Run Code Online (Sandbox Code Playgroud)