@@ -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,
@@ -483,32 +484,41 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
483484 * type MirroredMonoType = C[?]
484485 * ```
485486 */
486- def fromProductBody (caseClass : Symbol , param : Tree )(using Context ): Tree = {
487- val (classRef, methTpe) =
488- caseClass.primaryConstructor.info match {
487+ def fromProductBody (caseClass : Symbol , param : Tree , optInfo : Option [MirrorImpl .OfProduct ])(using Context ): Tree =
488+ def extractParams (tpe : Type ): List [Type ] =
489+ tpe.asInstanceOf [MethodType ].paramInfos
490+
491+ def computeFromCaseClass : (Type , List [Type ]) =
492+ val (baseRef, baseInfo) =
493+ val rawRef = caseClass.typeRef
494+ val rawInfo = caseClass.primaryConstructor.info
495+ optInfo match
496+ case Some (info) =>
497+ (rawRef.asSeenFrom(info.pre, caseClass.owner), rawInfo.asSeenFrom(info.pre, caseClass.owner))
498+ case _ =>
499+ (rawRef, rawInfo)
500+ baseInfo match
489501 case tl : PolyType =>
490502 val (tl1, tpts) = constrained(tl, untpd.EmptyTree , alwaysAddTypeVars = true )
491503 val targs =
492504 for (tpt <- tpts) yield
493505 tpt.tpe match {
494506 case tvar : TypeVar => tvar.instantiate(fromBelow = false )
495507 }
496- (caseClass.typeRef. appliedTo(targs), tl.instantiate(targs))
508+ (baseRef. appliedTo(targs), extractParams( tl.instantiate(targs) ))
497509 case methTpe =>
498- (caseClass.typeRef, methTpe)
499- }
500- methTpe match {
501- case methTpe : MethodType =>
502- val elems =
503- for ((formal, idx) <- methTpe.paramInfos.zipWithIndex) yield {
504- val elem =
505- param.select(defn.Product_productElement ).appliedTo(Literal (Constant (idx)))
506- .ensureConforms(formal.translateFromRepeated(toArray = false ))
507- if (formal.isRepeatedParam) ctx.typer.seqToRepeated(elem) else elem
508- }
509- New (classRef, elems)
510- }
511- }
510+ (baseRef, extractParams(methTpe))
511+ end computeFromCaseClass
512+
513+ val (classRefApplied, paramInfos) = computeFromCaseClass
514+ val elems =
515+ for ((formal, idx) <- paramInfos.zipWithIndex) yield
516+ val elem =
517+ param.select(defn.Product_productElement ).appliedTo(Literal (Constant (idx)))
518+ .ensureConforms(formal.translateFromRepeated(toArray = false ))
519+ if (formal.isRepeatedParam) ctx.typer.seqToRepeated(elem) else elem
520+ New (classRefApplied, elems)
521+ end fromProductBody
512522
513523 /** For an enum T:
514524 *
@@ -526,24 +536,36 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
526536 * a wildcard for each type parameter. The normalized type of an object
527537 * O is O.type.
528538 */
529- def ordinalBody (cls : Symbol , param : Tree )(using Context ): Tree =
530- if (cls.is(Enum )) param.select(nme.ordinal).ensureApplied
531- else {
539+ def ordinalBody (cls : Symbol , param : Tree , optInfo : Option [MirrorImpl .OfSum ])(using Context ): Tree =
540+ if cls.is(Enum ) then
541+ param.select(nme.ordinal).ensureApplied
542+ else
543+ def computeChildTypes : List [Type ] =
544+ def rawRef (child : Symbol ): Type =
545+ if (child.isTerm) child.reachableTermRef else child.reachableRawTypeRef
546+ optInfo match
547+ case Some (info) => info
548+ .childPres
549+ .lazyZip(cls.children)
550+ .map((pre, child) => rawRef(child).asSeenFrom(pre, child.owner))
551+ case _ =>
552+ cls.children.map(rawRef)
553+ end computeChildTypes
554+ val childTypes = computeChildTypes
532555 val cases =
533- for ((child, idx) <- cls.children.zipWithIndex) yield {
534- val patType = if (child.isTerm) child.reachableTermRef else child.reachableRawTypeRef
556+ for (patType, idx) <- childTypes.zipWithIndex yield
535557 val pat = Typed (untpd.Ident (nme.WILDCARD ).withType(patType), TypeTree (patType))
536558 CaseDef (pat, EmptyTree , Literal (Constant (idx)))
537- }
559+
538560 Match (param.annotated(New (defn.UncheckedAnnot .typeRef, Nil )), cases)
539- }
561+ end ordinalBody
540562
541563 /** - If `impl` is the companion of a generic sum, add `deriving.Mirror.Sum` parent
542564 * and `MirroredMonoType` and `ordinal` members.
543565 * - If `impl` is the companion of a generic product, add `deriving.Mirror.Product` parent
544566 * and `MirroredMonoType` and `fromProduct` members.
545- * - If `impl` is marked with one of the attachments ExtendsSingletonMirror, ExtendsProductMirror ,
546- * or ExtendsSumMirror, remove the attachment and generate the corresponding mirror support,
567+ * - If `impl` is marked with one of the attachments ExtendsSingletonMirror or ExtendsSumOfProductMirror ,
568+ * remove the attachment and generate the corresponding mirror support,
547569 * On this case the represented class or object is referred to in a pre-existing `MirroredMonoType`
548570 * member of the template.
549571 */
@@ -580,30 +602,33 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
580602 }
581603 def makeSingletonMirror () =
582604 addParent(defn.Mirror_SingletonClass .typeRef)
583- def makeProductMirror (cls : Symbol ) = {
605+ def makeProductMirror (cls : Symbol , optInfo : Option [ MirrorImpl . OfProduct ] ) = {
584606 addParent(defn.Mirror_ProductClass .typeRef)
585607 addMethod(nme.fromProduct, MethodType (defn.ProductClass .typeRef :: Nil , monoType.typeRef), cls,
586- fromProductBody(_, _).ensureConforms(monoType.typeRef)) // t4758.scala or i3381.scala are examples where a cast is needed
608+ fromProductBody(_, _, optInfo ).ensureConforms(monoType.typeRef)) // t4758.scala or i3381.scala are examples where a cast is needed
587609 }
588- def makeSumMirror (cls : Symbol ) = {
610+ def makeSumMirror (cls : Symbol , optInfo : Option [ MirrorImpl . OfSum ] ) = {
589611 addParent(defn.Mirror_SumClass .typeRef)
590612 addMethod(nme.ordinal, MethodType (monoType.typeRef :: Nil , defn.IntType ), cls,
591- ordinalBody(_, _))
613+ ordinalBody(_, _, optInfo ))
592614 }
593615
594616 if (clazz.is(Module )) {
595617 if (clazz.is(Case )) makeSingletonMirror()
596- else if (linked.isGenericProduct) makeProductMirror(linked)
597- else if (linked.isGenericSum) makeSumMirror(linked)
618+ else if (linked.isGenericProduct) makeProductMirror(linked, None )
619+ else if (linked.isGenericSum( NoType )) makeSumMirror(linked, None )
598620 else if (linked.is(Sealed ))
599- derive.println(i " $linked is not a sum because ${linked.whyNotGenericSum}" )
621+ derive.println(i " $linked is not a sum because ${linked.whyNotGenericSum( NoType ) }" )
600622 }
601623 else if (impl.removeAttachment(ExtendsSingletonMirror ).isDefined)
602624 makeSingletonMirror()
603- else if (impl.removeAttachment(ExtendsProductMirror ).isDefined)
604- makeProductMirror(monoType.typeRef.dealias.classSymbol)
605- else if (impl.removeAttachment(ExtendsSumMirror ).isDefined)
606- makeSumMirror(monoType.typeRef.dealias.classSymbol)
625+ else
626+ impl.removeAttachment(ExtendsSumOrProductMirror ).match
627+ case Some (prodImpl : MirrorImpl .OfProduct ) =>
628+ makeProductMirror(monoType.typeRef.dealias.classSymbol, Some (prodImpl))
629+ case Some (sumImpl : MirrorImpl .OfSum ) =>
630+ makeSumMirror(monoType.typeRef.dealias.classSymbol, Some (sumImpl))
631+ case _ =>
607632
608633 cpy.Template (impl)(parents = newParents, body = newBody)
609634 }
0 commit comments