Closed
Description
For now, Value classes are not provided Mirror.ProductOf
instances.
Something as below could be used.
transparent inline def valueClassProduct[
T <: AnyVal
]: Mirror.Product with Mirror.ProductOf[T] = ${ valueClassProductImpl[T] }
private def valueClassProductImpl[T: Type](
using
q: Quotes
): Expr[Mirror.Product with Mirror.ProductOf[T]] = {
import q.reflect.*
val tpr = TypeRepr.of[T]
if (defn.ScalaPrimitiveValueClasses.contains(tpr.typeSymbol)) {
report.errorAndAbort(s"Cannot derive primitive value class: ${tpr.show}")
}
// ---
val tprSym = tpr.typeSymbol
val ctor = tprSym.primaryConstructor
type IsString[U <: String] = U
ctor.paramSymss match {
case List(v: Symbol) :: Nil =>
v.tree match {
case vd: ValDef => {
(
ConstantType(StringConstant(tprSym.name)).asType,
vd.tpt.tpe.asType,
ConstantType(StringConstant(v.name)).asType
) match {
case (
'[IsString[label]],
'[fieldType],
'[IsString[fieldLabel]]
) =>
type ProductOfValue = Mirror.ProductOf[T] {
type MirroredType = T
type MirroredMonoType = T
type MirroredLabel = label
type MirroredElemTypes = Tuple1[fieldType]
type MirroredElemLabels = Tuple1[fieldLabel]
}
'{
(new Mirror.Product {
type MirroredType = T
type MirroredMonoType = T
type MirroredLabel = label
type MirroredElemTypes = Tuple1[fieldType]
type MirroredElemLabels = Tuple1[fieldLabel]
def fromProduct(p: Product): MirroredMonoType = ???
}): ProductOfValue
}
}
}
case term =>
report.errorAndAbort(
s"Value class is expected to have a single field: ${term.show}"
)
}
case args =>
report.errorAndAbort(
s"Value class is expected to have a single field: ${args mkString ", "}"
)
}
}
Usage:
final class Bar(val value: String) extends AnyVal
valueClassProduct[Bar]
// defined class Bar
val res0:
deriving.Mirror.ProductOf[Bar]{
MirroredType = Bar; MirroredMonoType = Bar; MirroredLabel = "Bar";
MirroredElemTypes = Tuple1[String]
; MirroredElemLabels = Tuple1["value"]
} = anon$1@4b8832f9
Metadata
Metadata
Assignees
Labels
No labels