scalagenericstypesslickcovariance

Type missmatch on Slick TableQuery


I am trying to have a generic type definition that can be satisfied by slicks TableQuery type:

  class OrderTable(tag: Tag) extends Table[Order](tag, "orders") 
     ...
  
  val orders = TableQuery[OrderTable]

  type Ta[X] = TableQuery[Table[X]]

  val orderTable: Ta[Order] = orders

What I want to achieve is that I have an abstract type definition in a trait that can be slick table but also something else like just a hashmap. I am getting the following compilation error:

found   : slick.jdbc.PostgresProfile.api.TableQuery[at.gepro.dbtemplate.OrderTable]
    (which expands to)  slick.lifted.TableQuery[at.gepro.dbtemplate.OrderTable]
 required: SlickOrderRepository.this.Ta[at.gepro.dbtemplate.Order]
    (which expands to)  slick.lifted.TableQuery[slick.jdbc.PostgresProfile.Table[at.gepro.dbtemplate.Order]]

I don't understand why this assignment does not work, everything uses the PostgresProfile api.

tried AbstractTable but did not work either


Solution

  • Because TableQuery is invariant

    class TableQuery[E <: AbstractTable[?]](cons: Tag => E) extends Query[E, E#TableElementType, Seq]
    

    https://github.com/slick/slick/blob/v3.5.0-M2/slick/src/main/scala/slick/lifted/Query.scala#L322

    It's not covariant TableQuery[+E <: AbstractTable[?]].

    OrderTable is a subtype of Table[Order] but TableQuery[OrderTable] is not a subtype of TableQuery[Table[Order]]

    implicitly[OrderTable <:< Table[Order]] // compiles
    // implicitly[TableQuery[OrderTable] <:< TableQuery[Table[Order]]] // doesn't compile
    

    Try:

    type Ta[X] = TableQuery[? <: Table[X]]
    // type Ta[X] = TableQuery[_ <: Table[X]] // former syntax
    
    val orderTable: Ta[Order] = orders
    

    What is an existential type?

    https://stackoverflow.com/questions/tagged/existential-type%2bscala?tab=Votes

    type Ta[X, T <: Table[X]] = TableQuery[T]
    
    val orderTable: Ta[Order, OrderTable] = orders
    

    You can read about variances in Scala:

    https://docs.scala-lang.org/tour/variances.html