I want to understand why inlining function fixes runtime error.
The following code results in a runtime error (see bellow)
[error] java.lang.ClassCastException: class Herbivore cannot be cast to class Food (Herbivore and Food are in unnamed module of loader sbt.internal.LayeredClassLoader @4837dd91)
trait GameObject
case class Food(x: Int) extends GameObject
case class Herbivore() extends GameObject
@main
def main: Unit =
val xs = Vector(Food(1), Herbivore(), Food(2))
def minBy[T <: GameObject](f: T => Double): Option[T] =
xs.collect{case v: T => v}.minByOption(f)
val done = minBy[Food](food => food.x)
println(done)
until i change it so minBy is inlined and works as intended(outputs: Some(Food(1))).
inline def minBy[T <: GameObject](f: T => Double): Option[T] = //-snip-
Is this intended behaviour?
Type erasure.
When JVM sees this code it can see only
Vector[GameObject]. Type test on generic parameter, well, it cannot be done because this parameter was not passed into method in runtime, so this check always succeeds.Since all values of xs will be passed into
finminByOptionand you have there not onlyFood, it will meed unexpected type.In Scala 2 you can add runtime test with
ClassTagbut I see that you are using Scala 3 which hasTypeTestwhich in your case should work with itsTypeablealias.It should behave as if you written manually: