Scala隐式TypeTag无法正确传播(隐式类型为Nothing)

时间:2013-12-18 19:41:52

标签: scala type-inference implicit

我在我的代码中广泛使用scala的2.10 TypeTag,我观察到一些与我不理解的类型推断相关的行为。

示例代码:

import scala.reflect.runtime.universe._

object BugDemo extends App {
  def printType[T <: AnyRef : TypeTag]() : T = { 
    println(typeOf[T]); 
    null.asInstanceOf[T]; 
  }

  case class Foo()

  var foo1 = printType[Foo]()
  var foo2 : Foo = printType[Foo]()
  var foo3 : Foo = printType()
}

现在我希望它打印Foo 3次,但实际上我得到了(scala 2.10.3):

BugDemo.Foo
BugDemo.Foo
Nothing

我的代码出了什么问题?为什么scala不想为T中的foo3传递正确的类型标记?

2 个答案:

答案 0 :(得分:3)

这没有错。

如果未指定type参数,则scala编译器采用最具体的类型。如果printType()Nothing(scala类型层次结构中的底部类型)。

由于NothingFoo的子类型,因此您的代码有效:

var foo3 : Foo = printType[Nothing]()

有趣的是,使用var foo3 : Nothing = printType[Nothing]()printType[Nothing](),您将获得NullPointerException

scala> var foo3 : Nothing = printType[Nothing]()
Nothing
java.lang.NullPointerException

scala> printType[Nothing]()
Nothing
java.lang.NullPointerException

您无法获取Nothing的实例,但您的代码(var foo3 : Foo = printType[Nothing]())因类型擦除而有效。它看起来像一个无法修复的scala bug。

答案 1 :(得分:0)

当调用者没有明确提供scala时,scala推断出的类型参数不是什么。我讨厌(HATE)这种默认行为,因为它会导致各种运行时错误。所有内容都不允许参数。

最好强制在requiring that its not Nothing编译时完全指定type参数:

sealed trait NotNothing[-T] 

object NotNothing {
  implicit object YoureSupposedToSupplyAType extends NotNothing[Nothing]
  implicit object notNothing extends NotNothing[Any] 
}

然后:

def printType[T : TypeTag : NotNothing]() : T = { ... }