3

As I played a bit with the Scala REPL (Scala 2.9.1) I saw a surprising result with the isInstanceOf method:

scala> val l = List[Int](1, 2, 3)
l: List[Int] = List(1, 2, 3)

scala> l.isInstanceOf[List[Int]]
warning: there were 1 unchecked warnings; re-run with -unchecked for details
res3: Boolean = true

scala> l.isInstanceOf[List[String]]
warning: there were 1 unchecked warnings; re-run with -unchecked for details
res4: Boolean = true

scala> l.isInstanceOf[List[Boolean]]
warning: there were 1 unchecked warnings; re-run with -unchecked for details
res5: Boolean = true

Can anyone explain the last two results ?

John Threepwood
  • 15,593
  • 27
  • 93
  • 149
  • 2
    Type erasure. See also http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens – Geo Jun 14 '12 at 21:17
  • 5
    "re-run with -unchecked for details". Did you do it? – Niklas B. Jun 14 '12 at 21:19
  • To blame myself: No, I did not. I could not figure out how to do that. If I use "compile -unchecked" at the sbt shell, it does not know this option. Where do I have to place this option ? – John Threepwood Jun 14 '12 at 21:28
  • 1
    Just call the Scala REPL with that additional argument: `scala -unchecked` – Niklas B. Jun 14 '12 at 21:29
  • Thanks, that worked. Is there a way to start the Scala REPL out of sbt with the unchecked option, too ? Within the sbt shell, the command 'console -unchecked' will fail. – John Threepwood Jun 14 '12 at 22:06
  • @JohnThreepwood That's worth another question, but you just have to set `scalacOptions`. On `build.sbt`, `scalacOptions += "-unchecked"`. Or, from sbt console, `set scalacOptions += "-unchecked"`. – Daniel C. Sobral Jun 14 '12 at 22:24

2 Answers2

11

re-running with -unchecked:

scala> l.isInstanceOf[List[Int]]
<console>:9: warning: non variable type-argument Int in type List[Int] is 
unchecked since it is eliminated by erasure
              l.isInstanceOf[List[Int]]
                        ^

The specific type of the object is just not known at runtime. This is a general feature/limitation of the generics mechanism provided by the JVM. See Type erasure for more information.

Niklas B.
  • 92,950
  • 18
  • 194
  • 224
5

It's due to type erasure which replaces the Int type parameter in List with the most generic type bound it can find. In this case, I believe that is scala.Any.

Note these will also yield true:

scala> l.isInstanceOf[List[scala.Nothing]]
warning: there were 1 unchecked warnings; re-run with -unchecked for details
res0: Boolean = true

scala> l.isInstanceOf[List[Any]]
warning: there were 1 unchecked warnings; re-run with -unchecked for details
res1: Boolean = true

scala> l.isInstanceOf[List[Object]]
warning: there were 1 unchecked warnings; re-run with -unchecked for details
res2: Boolean = true

Using javap to disassemble this simple class we can see that there is in fact no generic type in List[Int]:

class Bar{
  val list = List[Int](1,2,3)
}

The disassembled scala code:

public class Bar extends java.lang.Object implements scala.ScalaObject{
  public scala.collection.immutable.List list();
  public Bar();
}
Brian
  • 20,195
  • 6
  • 34
  • 55