Search code examples
scalatypestype-inferencecovariance

Scala compiler behaviour for Covariance


Following code is running perfectly :

abstract class Vehicle{
  val name:String
}
case class Car(name: String) extends Vehicle
case class Bike(name: String) extends Vehicle

case class Parking[T](vehicle: T)

object Covariance extends App {

  def parkMyVehicle(p : Parking[Vehicle]): Unit = println(s"Parking ${p.vehicle.name}")
  parkMyVehicle(Parking(Car("Mercedes")))
  parkMyVehicle(Parking(Bike("HD")))

}

This is bit strange, because, Parking is not covariant.

However, following line is demanding covariant Parking, else not getting compiled (which is expected).

parkMyVehicle(Parking[Car](Car("Mercedes")))

My question is, why parkMyVehicle(Parking(Car("Mercedes"))) was not demanding covariant Parking?


Solution

  • Because inference can figure out from the context what type should be. I.e.

    parkMyVehicle(Parking(Car("Mercedes")))
    //            ^ ---------------------^ What's the type of that?
    

    since parkMyVehicle takes Parking[Vehicle], that what the type should be from compiler PoV. So the expression gets typed with an upcast to a superclass:

    parkMyVehicle(Parking[Vehicle](Car("Mercedes"): Vehicle))
    

    This would be different if you extract variable, however:

    val p = Parking(Car("Mercedes")) // Type is first figured out to be Parking[Car]
    parkMyVehicle(p) // now the type of p does not match, so it fails to compile