Skip to content

Commit a459960

Browse files
add defaultArgument synthetic member to product mirrors in post-typer
1 parent e01fd46 commit a459960

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import Decorators.*
99
import NameOps.*
1010
import Annotations.Annotation
1111
import typer.ProtoTypes.constrained
12-
import ast.untpd
13-
12+
import ast.{tpd, untpd}
1413
import util.Property
1514
import util.Spans.Span
1615
import config.Printers.derive
@@ -83,6 +82,11 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
8382
private def synthesizeDef(sym: TermSymbol, rhsFn: List[List[Tree]] => Context ?=> Tree)(using Context): Tree =
8483
DefDef(sym, rhsFn(_)(using ctx.withOwner(sym))).withSpan(ctx.owner.span.focus)
8584

85+
private def synthesizeExperimentalDef(sym: TermSymbol, rhsFn: List[List[Tree]] => Context ?=> Tree)(using Context): Tree = {
86+
sym.addAnnotation(Annotation(defn.ExperimentalAnnot, sym.span))
87+
synthesizeDef(sym, rhsFn)
88+
}
89+
8690
/** If this is a case or value class, return the appropriate additional methods,
8791
* otherwise return nothing.
8892
*/
@@ -547,6 +551,29 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
547551
New(classRefApplied, elems)
548552
end fromProductBody
549553

554+
def defaultArgumentBody(caseClass: Symbol, index: Tree, optInfo: Option[MirrorImpl.OfProduct])(using Context): Tree =
555+
val companionTree: Tree =
556+
val companion: Symbol = caseClass.companionModule
557+
val prefix: Type = optInfo.fold(NoPrefix)(_.pre)
558+
ref(TermRef(prefix, companion.asTerm))
559+
560+
def defaultArgumentGetter(idx: Int): Tree =
561+
val getterName = NameKinds.DefaultGetterName(nme.CONSTRUCTOR, idx)
562+
val getterDenot = companionTree.tpe.member(getterName)
563+
companionTree.select(TermRef(companionTree.tpe, getterName, getterDenot))
564+
565+
val withDefaultCases =
566+
for (acc, idx) <- caseClass.caseAccessors.zipWithIndex if acc.is(HasDefault)
567+
yield CaseDef(Literal(Constant(idx)), EmptyTree, defaultArgumentGetter(idx))
568+
569+
val withoutDefaultCase =
570+
val stringIndex = Apply(Select(index, nme.toString_), Nil)
571+
val nsee = tpd.resolveConstructor(defn.NoSuchElementExceptionType, List(stringIndex))
572+
CaseDef(Underscore(defn.IntType), EmptyTree, Throw(nsee))
573+
574+
Match(index, withDefaultCases :+ withoutDefaultCase)
575+
end defaultArgumentBody
576+
550577
/** For an enum T:
551578
*
552579
* def ordinal(x: MirroredMonoType) = x.ordinal
@@ -616,6 +643,11 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
616643
synthesizeDef(meth, vrefss => body(cls, vrefss.head.head))
617644
}
618645
}
646+
def overrideMethod(name: TermName, info: Type, cls: Symbol, body: (Symbol, Tree) => Context ?=> Tree): Unit = { // TODO online override if changed
647+
val meth = newSymbol(clazz, name, Synthetic | Method | Override, info, coord = clazz.coord)
648+
meth.enteredAfter(thisPhase)
649+
newBody = newBody :+ synthesizeExperimentalDef(meth, vrefss => body(cls, vrefss.head.head))
650+
}
619651
val linked = clazz.linkedClass
620652
lazy val monoType = {
621653
val existing = clazz.info.member(tpnme.MirroredMonoType).symbol
@@ -633,6 +665,8 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
633665
addParent(defn.Mirror_ProductClass.typeRef)
634666
addMethod(nme.fromProduct, MethodType(defn.ProductClass.typeRef :: Nil, monoType.typeRef), cls,
635667
fromProductBody(_, _, optInfo).ensureConforms(monoType.typeRef)) // t4758.scala or i3381.scala are examples where a cast is needed
668+
if cls.primaryConstructor.hasDefaultParams then overrideMethod(nme.defaultArgument,
669+
MethodType(defn.IntType :: Nil, defn.AnyType), cls, defaultArgumentBody(_, _, optInfo))
636670
}
637671
def makeSumMirror(cls: Symbol, optInfo: Option[MirrorImpl.OfSum]) = {
638672
addParent(defn.Mirror_SumClass.typeRef)

0 commit comments

Comments
 (0)