Search code examples
scalatype-erasurescala-2.12

Why doesn't matching on a List[Any] generate an unchecked type warning?


Anyone know why these generate unchecked-type warnings...

def anyMap(a: Any): Unit = a match {
  case _: Map[Any, Any] => 
}
//warning: non-variable type argument Any in type pattern scala.collection.immutable.Map[Any,Any] (the underlying of Map[Any,Any]) is unchecked since it is eliminated by erasure

def intList(a: Any): Unit = a match {
  case _: List[Int] =>
}
//warning: non-variable type argument Int in type pattern List[Int] (the underlying of List[Int]) is unchecked since it is eliminated by erasure

...but this does not?

def anyList(a: Any): Unit = a match {
  case _: List[Any] =>
}
//[crickets]

Mostly just curious. Thanks


Solution

  • Scala can verify that the type of something satisfies List[Any] simply by checking that it is a List. This is because the list type is covariant in its first argument, so even if you pass it a List[Int] or a List[Double], those are still subclasses are List[Any], so all the compiler has to do is check List, which it can do at runtime. The type erasure doesn't affect its ability to do this.

    Checking if something is a List[Int] would require knowing the actual type of the elements, which is erased at runtime, and Scala can't do the same trick with Map[Any, Any] since the map type is invariant in its first argument. So while Map[Any, Int] is a subclass of Map[Any, Any], Map[Int, Any] is not. Thus, Scala would have to be able to check the type of the first argument, which it cannot do at runtime.

    More about variance can be found in the docs.