@@ -18,14 +18,15 @@ import NullOpsDecorator._
1818
1919object SyntheticMembers {
2020
21+ enum MirrorImpl :
22+ case OfProduct (pre : Type )
23+ case OfSum (childPres : List [Type ])
24+
2125 /** Attachment marking an anonymous class as a singleton case that will extend from Mirror.Singleton */
2226 val ExtendsSingletonMirror : Property .StickyKey [Unit ] = new Property .StickyKey
2327
2428 /** Attachment recording that an anonymous class should extend Mirror.Product */
25- val ExtendsProductMirror : Property .StickyKey [Unit ] = new Property .StickyKey
26-
27- /** Attachment recording that an anonymous class should extend Mirror.Sum */
28- val ExtendsSumMirror : Property .StickyKey [Unit ] = new Property .StickyKey
29+ val ExtendsSumOrProductMirror : Property .StickyKey [MirrorImpl ] = new Property .StickyKey
2930}
3031
3132/** Synthetic method implementations for case classes, case objects,
@@ -484,32 +485,41 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
484485 * type MirroredMonoType = C[?]
485486 * ```
486487 */
487- def fromProductBody (caseClass : Symbol , param : Tree )(using Context ): Tree = {
488- val (classRef, methTpe) =
489- caseClass.primaryConstructor.info match {
488+ def fromProductBody (caseClass : Symbol , param : Tree , optInfo : Option [MirrorImpl .OfProduct ])(using Context ): Tree =
489+ def extractParams (tpe : Type ): List [Type ] =
490+ tpe.asInstanceOf [MethodType ].paramInfos
491+
492+ def computeFromCaseClass : (Type , List [Type ]) =
493+ val (baseRef, baseInfo) =
494+ val rawRef = caseClass.typeRef
495+ val rawInfo = caseClass.primaryConstructor.info
496+ optInfo match
497+ case Some (info) =>
498+ (rawRef.asSeenFrom(info.pre, caseClass.owner), rawInfo.asSeenFrom(info.pre, caseClass.owner))
499+ case _ =>
500+ (rawRef, rawInfo)
501+ baseInfo match
490502 case tl : PolyType =>
491503 val (tl1, tpts) = constrained(tl, untpd.EmptyTree , alwaysAddTypeVars = true )
492504 val targs =
493505 for (tpt <- tpts) yield
494506 tpt.tpe match {
495507 case tvar : TypeVar => tvar.instantiate(fromBelow = false )
496508 }
497- (caseClass.typeRef. appliedTo(targs), tl.instantiate(targs))
509+ (baseRef. appliedTo(targs), extractParams( tl.instantiate(targs) ))
498510 case methTpe =>
499- (caseClass.typeRef, methTpe)
500- }
501- methTpe match {
502- case methTpe : MethodType =>
503- val elems =
504- for ((formal, idx) <- methTpe.paramInfos.zipWithIndex) yield {
505- val elem =
506- param.select(defn.Product_productElement ).appliedTo(Literal (Constant (idx)))
507- .ensureConforms(formal.translateFromRepeated(toArray = false ))
508- if (formal.isRepeatedParam) ctx.typer.seqToRepeated(elem) else elem
509- }
510- New (classRef, elems)
511- }
512- }
511+ (baseRef, extractParams(methTpe))
512+ end computeFromCaseClass
513+
514+ val (classRefApplied, paramInfos) = computeFromCaseClass
515+ val elems =
516+ for ((formal, idx) <- paramInfos.zipWithIndex) yield
517+ val elem =
518+ param.select(defn.Product_productElement ).appliedTo(Literal (Constant (idx)))
519+ .ensureConforms(formal.translateFromRepeated(toArray = false ))
520+ if (formal.isRepeatedParam) ctx.typer.seqToRepeated(elem) else elem
521+ New (classRefApplied, elems)
522+ end fromProductBody
513523
514524 /** For an enum T:
515525 *
@@ -527,24 +537,36 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
527537 * a wildcard for each type parameter. The normalized type of an object
528538 * O is O.type.
529539 */
530- def ordinalBody (cls : Symbol , param : Tree )(using Context ): Tree =
531- if (cls.is(Enum )) param.select(nme.ordinal).ensureApplied
532- else {
540+ def ordinalBody (cls : Symbol , param : Tree , optInfo : Option [MirrorImpl .OfSum ])(using Context ): Tree =
541+ if cls.is(Enum ) then
542+ param.select(nme.ordinal).ensureApplied
543+ else
544+ def computeChildTypes : List [Type ] =
545+ def rawRef (child : Symbol ): Type =
546+ if (child.isTerm) child.reachableTermRef else child.reachableRawTypeRef
547+ optInfo match
548+ case Some (info) => info
549+ .childPres
550+ .lazyZip(cls.children)
551+ .map((pre, child) => rawRef(child).asSeenFrom(pre, child.owner))
552+ case _ =>
553+ cls.children.map(rawRef)
554+ end computeChildTypes
555+ val childTypes = computeChildTypes
533556 val cases =
534- for ((child, idx) <- cls.children.zipWithIndex) yield {
535- val patType = if (child.isTerm) child.reachableTermRef else child.reachableRawTypeRef
557+ for (patType, idx) <- childTypes.zipWithIndex yield
536558 val pat = Typed (untpd.Ident (nme.WILDCARD ).withType(patType), TypeTree (patType))
537559 CaseDef (pat, EmptyTree , Literal (Constant (idx)))
538- }
560+
539561 Match (param.annotated(New (defn.UncheckedAnnot .typeRef, Nil )), cases)
540- }
562+ end ordinalBody
541563
542564 /** - If `impl` is the companion of a generic sum, add `deriving.Mirror.Sum` parent
543565 * and `MirroredMonoType` and `ordinal` members.
544566 * - If `impl` is the companion of a generic product, add `deriving.Mirror.Product` parent
545567 * and `MirroredMonoType` and `fromProduct` members.
546- * - If `impl` is marked with one of the attachments ExtendsSingletonMirror, ExtendsProductMirror ,
547- * or ExtendsSumMirror, remove the attachment and generate the corresponding mirror support,
568+ * - If `impl` is marked with one of the attachments ExtendsSingletonMirror or ExtendsSumOfProductMirror ,
569+ * remove the attachment and generate the corresponding mirror support,
548570 * On this case the represented class or object is referred to in a pre-existing `MirroredMonoType`
549571 * member of the template.
550572 */
@@ -581,30 +603,33 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
581603 }
582604 def makeSingletonMirror () =
583605 addParent(defn.Mirror_SingletonClass .typeRef)
584- def makeProductMirror (cls : Symbol ) = {
606+ def makeProductMirror (cls : Symbol , optInfo : Option [ MirrorImpl . OfProduct ] ) = {
585607 addParent(defn.Mirror_ProductClass .typeRef)
586608 addMethod(nme.fromProduct, MethodType (defn.ProductClass .typeRef :: Nil , monoType.typeRef), cls,
587- fromProductBody(_, _).ensureConforms(monoType.typeRef)) // t4758.scala or i3381.scala are examples where a cast is needed
609+ fromProductBody(_, _, optInfo ).ensureConforms(monoType.typeRef)) // t4758.scala or i3381.scala are examples where a cast is needed
588610 }
589- def makeSumMirror (cls : Symbol ) = {
611+ def makeSumMirror (cls : Symbol , optInfo : Option [ MirrorImpl . OfSum ] ) = {
590612 addParent(defn.Mirror_SumClass .typeRef)
591613 addMethod(nme.ordinal, MethodType (monoType.typeRef :: Nil , defn.IntType ), cls,
592- ordinalBody(_, _))
614+ ordinalBody(_, _, optInfo ))
593615 }
594616
595617 if (clazz.is(Module )) {
596618 if (clazz.is(Case )) makeSingletonMirror()
597- else if (linked.isGenericProduct) makeProductMirror(linked)
598- else if (linked.isGenericSum) makeSumMirror(linked)
619+ else if (linked.isGenericProduct) makeProductMirror(linked, None )
620+ else if (linked.isGenericSum( NoType )) makeSumMirror(linked, None )
599621 else if (linked.is(Sealed ))
600- derive.println(i " $linked is not a sum because ${linked.whyNotGenericSum}" )
622+ derive.println(i " $linked is not a sum because ${linked.whyNotGenericSum( NoType ) }" )
601623 }
602624 else if (impl.removeAttachment(ExtendsSingletonMirror ).isDefined)
603625 makeSingletonMirror()
604- else if (impl.removeAttachment(ExtendsProductMirror ).isDefined)
605- makeProductMirror(monoType.typeRef.dealias.classSymbol)
606- else if (impl.removeAttachment(ExtendsSumMirror ).isDefined)
607- makeSumMirror(monoType.typeRef.dealias.classSymbol)
626+ else
627+ impl.removeAttachment(ExtendsSumOrProductMirror ).match
628+ case Some (prodImpl : MirrorImpl .OfProduct ) =>
629+ makeProductMirror(monoType.typeRef.dealias.classSymbol, Some (prodImpl))
630+ case Some (sumImpl : MirrorImpl .OfSum ) =>
631+ makeSumMirror(monoType.typeRef.dealias.classSymbol, Some (sumImpl))
632+ case _ =>
608633
609634 cpy.Template (impl)(parents = newParents, body = newBody)
610635 }
0 commit comments