scala/scala3

cached derived instance loses refinements

Open

#10,031 opened on Oct 18, 2020

View on GitHub
 (9 comments) (0 reactions) (0 assignees)Scala (6,247 stars) (1,159 forks)batch import
help wanteditype:bugitype:enhancement

Description

Minimized code

package example

trait Sealed[A] {
  type NumCases <: Int
}

object Sealed {
  import quoted._

  transparent inline def derived[A]: Sealed[A] = ${ deriveSealed[A] }

  def deriveSealed[A: Type](using Quotes): Expr[Sealed[A]] =
    import quotes.reflect._

    val tpe = TypeRepr.of[A]

    val sym = tpe.classSymbol match
      case Some(sym) => sym
      case _         => report.throwError(s"${tpe.show} is not a class type")

    val numCases = ConstantType(IntConstant(sym.children.length)).asType.asInstanceOf[quoted.Type[Int]]

    '{
      new {
        type NumCases = numCases.Underlying
      }
    }
}
// second source

import example._

enum MyEnum derives Sealed { case A, B, C }

val fromDerived = summon[Sealed[MyEnum]] // : example.Sealed[MyEnum]
val manual = Sealed.derived[MyEnum] // : example.Sealed[MyEnum]{NumCases = 3}

Expectation

I would expect the cached values to remember type refinements, so e.g. the derived Sealed instance can be used in further type class derivation to extract the NumCases type

Contributor guide