@@ -18,14 +18,15 @@ import NullOpsDecorator._
18
18
19
19
object SyntheticMembers {
20
20
21
+ enum MirrorImpl :
22
+ case OfProduct (pre : Type )
23
+ case OfSum (childPres : List [Type ])
24
+
21
25
/** Attachment marking an anonymous class as a singleton case that will extend from Mirror.Singleton */
22
26
val ExtendsSingletonMirror : Property .StickyKey [Unit ] = new Property .StickyKey
23
27
24
28
/** 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
29
30
}
30
31
31
32
/** Synthetic method implementations for case classes, case objects,
@@ -483,32 +484,41 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
483
484
* type MirroredMonoType = C[?]
484
485
* ```
485
486
*/
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
489
501
case tl : PolyType =>
490
502
val (tl1, tpts) = constrained(tl, untpd.EmptyTree , alwaysAddTypeVars = true )
491
503
val targs =
492
504
for (tpt <- tpts) yield
493
505
tpt.tpe match {
494
506
case tvar : TypeVar => tvar.instantiate(fromBelow = false )
495
507
}
496
- (caseClass.typeRef. appliedTo(targs), tl.instantiate(targs))
508
+ (baseRef. appliedTo(targs), extractParams( tl.instantiate(targs) ))
497
509
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
512
522
513
523
/** For an enum T:
514
524
*
@@ -526,24 +536,36 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
526
536
* a wildcard for each type parameter. The normalized type of an object
527
537
* O is O.type.
528
538
*/
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
532
555
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
535
557
val pat = Typed (untpd.Ident (nme.WILDCARD ).withType(patType), TypeTree (patType))
536
558
CaseDef (pat, EmptyTree , Literal (Constant (idx)))
537
- }
559
+
538
560
Match (param.annotated(New (defn.UncheckedAnnot .typeRef, Nil )), cases)
539
- }
561
+ end ordinalBody
540
562
541
563
/** - If `impl` is the companion of a generic sum, add `deriving.Mirror.Sum` parent
542
564
* and `MirroredMonoType` and `ordinal` members.
543
565
* - If `impl` is the companion of a generic product, add `deriving.Mirror.Product` parent
544
566
* 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,
547
569
* On this case the represented class or object is referred to in a pre-existing `MirroredMonoType`
548
570
* member of the template.
549
571
*/
@@ -580,30 +602,33 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
580
602
}
581
603
def makeSingletonMirror () =
582
604
addParent(defn.Mirror_SingletonClass .typeRef)
583
- def makeProductMirror (cls : Symbol ) = {
605
+ def makeProductMirror (cls : Symbol , optInfo : Option [ MirrorImpl . OfProduct ] ) = {
584
606
addParent(defn.Mirror_ProductClass .typeRef)
585
607
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
587
609
}
588
- def makeSumMirror (cls : Symbol ) = {
610
+ def makeSumMirror (cls : Symbol , optInfo : Option [ MirrorImpl . OfSum ] ) = {
589
611
addParent(defn.Mirror_SumClass .typeRef)
590
612
addMethod(nme.ordinal, MethodType (monoType.typeRef :: Nil , defn.IntType ), cls,
591
- ordinalBody(_, _))
613
+ ordinalBody(_, _, optInfo ))
592
614
}
593
615
594
616
if (clazz.is(Module )) {
595
617
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 )
598
620
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 ) }" )
600
622
}
601
623
else if (impl.removeAttachment(ExtendsSingletonMirror ).isDefined)
602
624
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 _ =>
607
632
608
633
cpy.Template (impl)(parents = newParents, body = newBody)
609
634
}
0 commit comments