Skip to content

Commit d1f7555

Browse files
committed
use TupleMirror for tuple mirrors
1 parent 1732445 commit d1f7555

File tree

3 files changed

+19
-21
lines changed

3 files changed

+19
-21
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,8 @@ class Definitions {
915915

916916
def TupleXXL_fromIterator(using Context): Symbol = TupleXXLModule.requiredMethod("fromIterator")
917917

918+
@tu lazy val RuntimeTupleMirrorTypeRef: TypeRef = requiredClassRef("scala.runtime.TupleMirror")
919+
918920
@tu lazy val RuntimeTuplesModule: Symbol = requiredModule("scala.runtime.Tuples")
919921
@tu lazy val RuntimeTuplesModuleClass: Symbol = RuntimeTuplesModule.moduleClass
920922
lazy val RuntimeTuples_consIterator: Symbol = RuntimeTuplesModule.requiredMethod("consIterator")

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ object SyntheticMembers {
2626

2727
/** Attachment recording that an anonymous class should extend Mirror.Sum */
2828
val ExtendsSumMirror: Property.StickyKey[Unit] = new Property.StickyKey
29-
30-
/** Attachment recording that an anonymous class (with the ExtendsProductMirror attachment)
31-
* should implement its `fromProduct` method in terms of the runtime class corresponding
32-
* to a tuple with that arity.
33-
*/
34-
val GenericTupleArity: Property.StickyKey[Int] = new Property.StickyKey
3529
}
3630

3731
/** Synthetic method implementations for case classes, case objects,
@@ -607,11 +601,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
607601
else if (impl.removeAttachment(ExtendsSingletonMirror).isDefined)
608602
makeSingletonMirror()
609603
else if (impl.removeAttachment(ExtendsProductMirror).isDefined)
610-
val tupleArity = impl.removeAttachment(GenericTupleArity)
611-
val cls = tupleArity match
612-
case Some(n) => defn.TupleType(n).nn.classSymbol
613-
case _ => monoType.typeRef.dealias.classSymbol
614-
makeProductMirror(cls)
604+
makeProductMirror(monoType.typeRef.dealias.classSymbol)
615605
else if (impl.removeAttachment(ExtendsSumMirror).isDefined)
616606
makeSumMirror(monoType.typeRef.dealias.classSymbol)
617607

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -223,19 +223,16 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
223223
/** Create an anonymous class `new Object { type MirroredMonoType = ... }`
224224
* and mark it with given attachment so that it is made into a mirror at PostTyper.
225225
*/
226-
private def anonymousMirror(monoType: Type, attachment: Property.StickyKey[Unit], tupleArity: Option[Int], span: Span)(using Context) =
226+
private def anonymousMirror(monoType: Type, attachment: Property.StickyKey[Unit], span: Span)(using Context) =
227227
if ctx.isAfterTyper then ctx.compilationUnit.needsMirrorSupport = true
228228
val monoTypeDef = untpd.TypeDef(tpnme.MirroredMonoType, untpd.TypeTree(monoType))
229-
var newImpl = untpd.Template(
229+
val newImpl = untpd.Template(
230230
constr = untpd.emptyConstructor,
231231
parents = untpd.TypeTree(defn.ObjectType) :: Nil,
232232
derived = Nil,
233233
self = EmptyValDef,
234234
body = monoTypeDef :: Nil
235235
).withAttachment(attachment, ())
236-
tupleArity.foreach { n =>
237-
newImpl = newImpl.withAttachment(GenericTupleArity, n)
238-
}
239236
typer.typed(untpd.New(newImpl).withSpan(span))
240237

241238
/** The mirror type
@@ -385,12 +382,17 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
385382

386383
private def productMirror(mirroredType: Type, formal: Type, span: Span)(using Context): TreeWithErrors =
387384

385+
/** `new scala.runtime.TupleMirror(arity)`
386+
* using TupleMirror avoids generating anonymous classes for tuple mirrors.
387+
*/
388+
def newTupleMirror(arity: Int): Tree =
389+
New(defn.RuntimeTupleMirrorTypeRef, Literal(Constant(arity)) :: Nil)
390+
388391
def makeProductMirror(cls: Symbol, tps: Option[List[Type]]): TreeWithErrors =
389392
val accessors = cls.caseAccessors.filterNot(_.isAllOf(PrivateLocal))
390393
val elemLabels = accessors.map(acc => ConstantType(Constant(acc.name.toString)))
391-
val nestedPairs =
392-
val elems = tps.getOrElse(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
393-
TypeOps.nestedPairs(elems)
394+
val typeElems = tps.getOrElse(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
395+
val nestedPairs = TypeOps.nestedPairs(typeElems)
394396
val (monoType, elemsType) = mirroredType match
395397
case mirroredType: HKTypeLambda =>
396398
(mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
@@ -406,7 +408,11 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
406408
}
407409
val mirrorRef =
408410
if cls.useCompanionAsProductMirror then companionPath(mirroredType, span)
409-
else anonymousMirror(monoType, ExtendsProductMirror, tps.map(_.size), span)
411+
else
412+
if defn.isTupleClass(cls) then // add `|| cls == defn.PairClass` when we support TupleXXL
413+
newTupleMirror(arity = typeElems.size)
414+
else
415+
anonymousMirror(monoType, ExtendsProductMirror, span)
410416
withNoErrors(mirrorRef.cast(mirrorType))
411417
end makeProductMirror
412418

@@ -508,7 +514,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
508514
}
509515
val mirrorRef =
510516
if cls.useCompanionAsSumMirror then companionPath(mirroredType, span)
511-
else anonymousMirror(monoType, ExtendsSumMirror, None, span)
517+
else anonymousMirror(monoType, ExtendsSumMirror, span)
512518
withNoErrors(mirrorRef.cast(mirrorType))
513519
else if acceptableMsg.nonEmpty then
514520
withErrors(i"type `$mirroredType` is not a generic sum because $acceptableMsg")

0 commit comments

Comments
 (0)