Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential issue with deriving type classes that are already based on Mirrors #182

Open
matwojcik opened this issue Dec 20, 2024 · 2 comments

Comments

@matwojcik
Copy link

Hi,

I have a typeclass which is generated using Mirrors. There is a compilation failure returned when I use UnionDerivation on top of it.

Take a look at this minimal example:

//> using scala "3.5.2"
//> using lib "io.github.irevive::union-derivation-core:0.2.1"
//> using options "-Yretain-trees"

import scala.annotation.nowarn
import scala.deriving.Mirror

import io.github.irevive.union.derivation.IsUnion
import io.github.irevive.union.derivation.UnionDerivation

trait Show[A] {
  def show(value: A): String
}

object Show {
  inline given derivedUnion[A](using IsUnion[A]): Show[A] = UnionDerivation.derive[Show, A]

  @nowarn("msg=New anonymous class definition will be duplicated at each inline site")
  inline given instance[A](using m: Mirror.ProductOf[A]): Show[A] = {
    println(s"$m") // if you remove it, then it compiles
    new Show[A] {
      def show(value: A): String = value.toString()
    }
  }
}

case class A(x: String)
case class B(y: Int)

// it also compiles when you uncomment those:
// given Show[A] = Show.instance[A]
// given Show[B] = Show.instance[B]

@main def hello() = println(Show.derivedUnion[A | B].show(A("1")))

It returns

Error: Error while emitting example.scala
val m$proxy1

The error goes away if you either don't use the mirror (even if you declare it in using clause) or if you generate the instances outside of UnionDerivation macro.

@iRevive
Copy link
Owner

iRevive commented Dec 31, 2024

This change made the snippet compile:

- inline given instance[A](using m: Mirror.ProductOf[A]): Show[A] = {
+ inline given instance[A](using inline m: Mirror.ProductOf[A]): Show[A] = {

It may be a non-trivial compiler issue, but I didn't dive into it, to be honest.

@matwojcik
Copy link
Author

Since 3.3.0 it is going to fail scala/scala3#16804 when you use anything from this inlined param (like m.MirroredElemLabels) - see this for context.

(m : scala.deriving.Mirror.ProductOf[A]) is not a valid type prefix, since it is not an immutable path
[error]    |Inline parameters are not considered immutable paths and cannot be used as
[error]    |singleton types.
[error]    |
[error]    |Hint: Removing the `inline` qualifier from the `m` parameter
[error]    |may help resolve this issue.

I can see that they witnessed issues with it in circe - circe/circe#2287 / circe/circe#2278

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants