softwaremill/quicklens

Unable to perform `at` with a derived key in Scala 3

OndrejSpanel opened this issue · 3 comments

Following code compiles and runs fine with Scala 2.13.12, but it does not compile with Scala 3.3.1:

import com.softwaremill.quicklens._

object Main {
  trait E
  trait X extends E

  case class Id[+T](id: Int)

  def main(args: Array[String]): Unit = {
    val map = Map[Id[E], Set[Int]](Id[X](0) -> Set.empty)

    map.modify(_.at(Id[X](0))).using(s => s)

  }
}

The error is:

C:\Dev\scala3compat\src\main\scala\Main.scala:12:30
No given instance of type com.softwaremill.quicklens.QuicklensIndexedFunctor[
  [V] =>> Map[Main.Id[Main.E], V], Main.Id[Main.X]] was found for an implicit parameter of method at in package com.softwaremill.quicklens.
I found:

    com.softwaremill.quicklens.QuicklensIndexedFunctor.
      given_QuicklensIndexedFunctor_M_K[K, M]

But given instance given_QuicklensIndexedFunctor_M_K in
  object QuicklensIndexedFunctor does not match type com.softwaremill.quicklens.QuicklensIndexedFunctor[
  [V] =>> Map[Main.Id[Main.E], V], Main.Id[Main.X]].
    map.modify(_.at(Id[X](0))).using(s => s)

I'm not sure if this is a bug in Scala 3, Map is invariant in the key type.

The Map[E, V] is invariant in E, but is allows get or updated using X, because instance of X is instance of E. The necessary type should be inferred in at. Following expressions works fine even in Scala 3:

    map.get(Id[X](0))
    map.updated(Id[X](0), Set.empty)

Simplified repro which also does not work in Scala 3:

import com.softwaremill.quicklens._

object Main {
  class E
  class X extends E

  def main(args: Array[String]): Unit = {
    val x = new X
    val map = Map[E, Int](x -> 0)
    map.modify(_.at(x)).using(s => s)
  }
}