Skip to content

Regression: Unrepresentable invalid type inferred in implicit search with a HKT type lambda using a library type and ignoring some of its arguments, when variance is used on HKT parameters #15888

Open
@neko-kai

Description

@neko-kai

Compiler version

3.1.3

Minimized code

Scastie: https://scastie.scala-lang.org/pz6QIrsKQqe6qrdZDeSLvg

Using -Ykind-projector

object x {
  sealed trait ZIO[-R, +E, +A] extends ZIOVersionSpecific[R, E, A]
  // this trait is required for the error to surface
  trait ZIOVersionSpecific[-R, +E, +A]

  type IO[+E, +A] = ZIO[Any, E, A]
}

object example {

  import x.{IO, ZIO}

  trait Panic3[F[-_, +_, +_]] extends Root

  type Panic2[F[+_, +_]] = Panic3[λ[(`-R`, `+E`, `+A`) => F[E, A]]]

  trait Root
  object Root extends RootInstancesLowPriority7

  sealed trait RootInstancesLowPriority7 extends RootInstancesLowPriority12 {
    @inline implicit final def BIOZIO: Panic3[ZIO] = null
  }

  sealed trait RootInstancesLowPriority12 {
    @inline implicit final def Convert3To2[C[f[-_, +_, +_]] <: Root, FR[-_, +_, +_], R0](
      implicit BifunctorPlus: Root & C[FR] // `Root &` required due to https://github.com/lampepfl/dotty/issues/13986
    ): C[λ[(`-R`, `+E`, `+A`) => FR[R0, E, A]]] = {
      BifunctorPlus.asInstanceOf[C[λ[(`-R`, `+E`, `+A`) => FR[R0, E, A]]]]
    }
  }

  trait FreeMonad[F[+_, +_], +E, +A] {
    @inline def foldMap[G[+_, +_], E, A](fg: Interpreter[F, G])(implicit G: Panic2[G]): G[E, A] = null.asInstanceOf[G[E, A]]
  }

  // NOTE: variance on Interpreter parameters is required for the error, removing variance makes it disappear
  // type Interpreter[Source[+_, +_], Target[+_, +_]]
  type Interpreter[-Source[+_, +_], +Target[+_, +_]]

  sealed trait TestFreeChoice[+E, +A]

  @main def main: Unit = {
    println(
      implicitly[Panic2[IO]]
    )
    println(
      implicitly[Panic2[λ[(`+E`, `+A`) => ZIO[Any, E, A]]]]
    )

    val interpreter: Interpreter[TestFreeChoice, IO] = null.asInstanceOf[Interpreter[TestFreeChoice, IO]]
    val value: FreeMonad[TestFreeChoice, Nothing, Unit] = new FreeMonad[TestFreeChoice, Nothing, Unit] {}
    println(value.foldMap(interpreter))
  }

}

Output

no given instance of type example.Panic2[([E, A] =>> zio.ZIO[Any, E, A])] was found for parameter G of method foldMap in trait FreeMonad.
I found:

    example.Root.Convert3To2[C, FR, R0]

But method Convert3To2 in trait RootInstancesLowPriority12 does not match type example.Panic2[([E, A] =>> zio.ZIO[Any, E, A])].

However, searching for the implicit with the quoted type immediately works: implicitly[example.Panic2[([E, A] =>> zio.ZIO[Any, E, A])]], as does giving explicit type argument to foldMap

The bug only surfaces with inference with 2 specific conditions: Variance annotations on Interpreter and type x.ZIO must inherit another trait trait ZIOVersionSpecific[-R, +E, +A]

Expectation

Expected to work, as in Scala 2 https://scastie.scala-lang.org/jdr2LjLzT3e9eaztflgzSQ

This code is a minimized version of real library code in https://github.com/izumi/izumi which we're trying to port to Scala 3

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions