Closed
Description
Compiler version
3.3.3
Minimized code
repro.scala
//> using scala 3.3.3
import scala.quoted.*
object Macros {
def valuesImpl[A: Type](using quotes: Quotes): Expr[List[A]] = {
import quotes.*, quotes.reflect.*
extension (sym: Symbol)
def isPublic: Boolean = !sym.isNoSymbol &&
!(sym.flags.is(Flags.Private) || sym.flags.is(Flags.PrivateLocal) || sym.flags.is(Flags.Protected) ||
sym.privateWithin.isDefined || sym.protectedWithin.isDefined)
def isSealed[A: Type]: Boolean =
TypeRepr.of[A].typeSymbol.flags.is(Flags.Sealed)
def extractSealedSubtypes[A: Type]: List[Type[?]] = {
def extractRecursively(sym: Symbol): List[Symbol] =
if sym.flags.is(Flags.Sealed) then sym.children.flatMap(extractRecursively)
else if sym.flags.is(Flags.Enum) then List(sym.typeRef.typeSymbol)
else if sym.flags.is(Flags.Module) then List(sym.typeRef.typeSymbol.moduleClass)
else List(sym)
extractRecursively(TypeRepr.of[A].typeSymbol).distinct.map(typeSymbol =>
typeSymbol.typeRef.asType
)
}
if isSealed[A] then {
val refs = extractSealedSubtypes[A].flatMap { tpe =>
val sym = TypeRepr.of(using tpe).typeSymbol
val isCaseVal = sym.isPublic && sym.flags
.is(Flags.Case | Flags.Enum) && (sym.flags.is(Flags.JavaStatic) || sym.flags.is(Flags.StableRealizable))
if (isCaseVal) then List(Ref(sym).asExprOf[A])
else Nil
}
Expr.ofList(refs)
} else '{ Nil }
}
inline def values[A]: List[A] = ${ valuesImpl[A] }
}
repro.test.sc
//> using dep org.scalameta::munit:1.0.0-RC1
object domain:
enum PaymentMethod:
case PayPal(email: String)
case Card(digits: Long, name: String)
case Cash
println(Macros.values[domain.PaymentMethod])
scala-cli test .
Output
Compiling project (Scala 3.3.3, JVM (17))
Error compiling project (Scala 3.3.3, JVM (17))
Error: Unexpected error when compiling eldupa7_d832c8dfee: java.lang.AssertionError: assertion failed: missing outer accessor in class repro$u002Etest$_
Expectation
repro.test.sc
should compile successfully (and print something like List(Cash)
).