Search code examples
scalavectorfunctional-programmingclasscastexceptionimmutable-collections

scala.collection.immutable.Vector cannot be cast to <My Class>


I am perplexed why I cannot yield a collection from the following line of Scala code:

val pairs = for( v <- vc; o <- oc) yield (v,o)

It's inside of this function, which is using immutable Vectors.

 private def recMergeVirtualAndReal(mCell: RCell, vc: Vector[Cell], oc: Vector[Cell]): Vector[Cell] = {
        var temp_oc = oc
        val pairs = for( v <- vc; o <- oc) yield (v,o)
        val newVCells =
          for((left, right) <- pairs if left contains right) yield {
            temp_oc = temp_oc.filterNot(o => o == left || o == right)
            captureVCells(left,right,mCell)
          }
        if(newVCells.nonEmpty) recMergeVirtualAndReal(mCell, recMergeVirtualCells(newVCells ++ vc), temp_oc)
        else vc
      }

I get the following error in the stack trace:

Exception in thread "main" java.lang.ClassCastException: scala.collection.immutable.Vector cannot be cast to game.Cell
    at model.Board$$anonfun$10.apply(Board.scala:223)
    at scala.collection.immutable.List.flatMap(List.scala:327)

I'm confused because I am not trying to cast anything, its just a simple statement without any type conversions.

I also tried this in case the compiler couldn't understand the types:

val pairs = for( v: Cell <- vc: Vector[Cell]; o: Cell <- oc: Vector[Cell]) yield (v: Cell,o: Cell)

Solution

  • You are probably doing an unsafe cast somewhere in the calling code. Check the arguments to your function, and check especially for uses of asInstanceOf.

    Here's an example of how an unsafe cast could cause this problem. First, we create a List[Int], then force the compiler to think of it as a List[String].

    val ls = List(1).asInstanceOf[List[String]]
    

    This works, as the Scala compiler is okay with it, and the generics are unchecked at runtime until we try to store an element of the list to a variable:

    val x = ls.head  // java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String
    

    Probably, somewhere else in your code, you are calling .asInstanceOf[Vector[Cell]] on a Vector[Vector[Something]], then passing it to this function. Never use asInstanceOf if you can help it.