@@ -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,
@@ -484,32 +485,41 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
484
485
* type MirroredMonoType = C[?]
485
486
* ```
486
487
*/
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
490
502
case tl : PolyType =>
491
503
val (tl1, tpts) = constrained(tl, untpd.EmptyTree , alwaysAddTypeVars = true )
492
504
val targs =
493
505
for (tpt <- tpts) yield
494
506
tpt.tpe match {
495
507
case tvar : TypeVar => tvar.instantiate(fromBelow = false )
496
508
}
497
- (caseClass.typeRef. appliedTo(targs), tl.instantiate(targs))
509
+ (baseRef. appliedTo(targs), extractParams( tl.instantiate(targs) ))
498
510
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
513
523
514
524
/** For an enum T:
515
525
*
@@ -527,24 +537,36 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
527
537
* a wildcard for each type parameter. The normalized type of an object
528
538
* O is O.type.
529
539
*/
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
533
556
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
536
558
val pat = Typed (untpd.Ident (nme.WILDCARD ).withType(patType), TypeTree (patType))
537
559
CaseDef (pat, EmptyTree , Literal (Constant (idx)))
538
- }
560
+
539
561
Match (param.annotated(New (defn.UncheckedAnnot .typeRef, Nil )), cases)
540
- }
562
+ end ordinalBody
541
563
542
564
/** - If `impl` is the companion of a generic sum, add `deriving.Mirror.Sum` parent
543
565
* and `MirroredMonoType` and `ordinal` members.
544
566
* - If `impl` is the companion of a generic product, add `deriving.Mirror.Product` parent
545
567
* 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,
548
570
* On this case the represented class or object is referred to in a pre-existing `MirroredMonoType`
549
571
* member of the template.
550
572
*/
@@ -581,30 +603,33 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
581
603
}
582
604
def makeSingletonMirror () =
583
605
addParent(defn.Mirror_SingletonClass .typeRef)
584
- def makeProductMirror (cls : Symbol ) = {
606
+ def makeProductMirror (cls : Symbol , optInfo : Option [ MirrorImpl . OfProduct ] ) = {
585
607
addParent(defn.Mirror_ProductClass .typeRef)
586
608
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
588
610
}
589
- def makeSumMirror (cls : Symbol ) = {
611
+ def makeSumMirror (cls : Symbol , optInfo : Option [ MirrorImpl . OfSum ] ) = {
590
612
addParent(defn.Mirror_SumClass .typeRef)
591
613
addMethod(nme.ordinal, MethodType (monoType.typeRef :: Nil , defn.IntType ), cls,
592
- ordinalBody(_, _))
614
+ ordinalBody(_, _, optInfo ))
593
615
}
594
616
595
617
if (clazz.is(Module )) {
596
618
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 )
599
621
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 ) }" )
601
623
}
602
624
else if (impl.removeAttachment(ExtendsSingletonMirror ).isDefined)
603
625
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 _ =>
608
633
609
634
cpy.Template (impl)(parents = newParents, body = newBody)
610
635
}
0 commit comments