Вопрос

I'm using scala's 2.10 TypeTags extensively in my code and I observe some behavior related to type inference that I do not understand.

Example code:

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()
}

Now I expect it to print Foo 3 times, but in reality I get (scala 2.10.3):

BugDemo.Foo
BugDemo.Foo
Nothing

What's wrong with my code? Why doesn't scala want to pass a proper type tag for my T in foo3?

Это было полезно?

Решение

Here is nothing wrong.

With type parameter not specified scala compiler takes the most concrete type. In case of printType() it's Nothing (the bottom type in scala type hierarchy).

Since Nothing is subtype of Foo your code is valid:

var foo3 : Foo = printType[Nothing]()

Funny thing is that with var foo3 : Nothing = printType[Nothing]() or even with printType[Nothing]() you'll get a NullPointerException:

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

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

You can't get an instance of Nothing, but your code (var foo3 : Foo = printType[Nothing]()) works due to the type erasure. It looks like a scala bug that can't be fixed.

Другие советы

Nothing is the type parameter inferred by scala when one isn't explicitly provided by the caller. I hate (HATE) this default behavior because is leads to all sorts of runtime bugs Nothing is an allowed parameter to everything.

Its much better to enforce that the type parameter should be fully specified at compile-time by requiring that its not Nothing:

sealed trait NotNothing[-T] 

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

and then:

def printType[T : TypeTag : NotNothing]() : T = { ... }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top