Skip to content

Commit 90a9067

Browse files
committed
Support Mirror for generic tuples arity > 22
1 parent 4d50e5f commit 90a9067

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

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

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -432,13 +432,24 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
432432
makeProductMirror(typeElems, elemLabels, tpnme.NamedTuple, mirrorRef)
433433
end makeNamedTupleProductMirror
434434

435+
def makeTupleProductMirror(tps: List[Type]): TreeWithErrors =
436+
val arity = tps.size
437+
if arity < Definitions.MaxTupleArity then
438+
val tupleCls = defn.TupleType(arity).nn.classSymbol
439+
makeClassProductMirror(tupleCls.owner.reachableThisType, tupleCls, Some(tps))
440+
else
441+
val elemLabels = (for i <- 1 to arity yield ConstantType(Constant(s"_$i"))).toList
442+
val mirrorRef: Type => Tree = _ => newTupleMirror(arity)
443+
makeProductMirror(tps, elemLabels, s"Tuple$arity".toTermName, mirrorRef)
444+
end makeTupleProductMirror
445+
435446
def makeClassProductMirror(pre: Type, cls: Symbol, tps: Option[List[Type]]) =
436447
val accessors = cls.caseAccessors
437448
val elemLabels = accessors.map(acc => ConstantType(Constant(acc.name.toString)))
438449
val typeElems = tps.getOrElse(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
439450
val mirrorRef = (monoType: Type) =>
440451
if cls.useCompanionAsProductMirror then companionPath(pre, cls, span)
441-
else if defn.isTupleClass(cls) then newTupleMirror(typeElems.size) // TODO: cls == defn.PairClass when > 22
452+
else if defn.isTupleClass(cls) then newTupleMirror(typeElems.size)
442453
else anonymousMirror(monoType, MirrorImpl.OfProduct(pre), span)
443454
makeProductMirror(typeElems, elemLabels, cls.name, mirrorRef)
444455
end makeClassProductMirror
@@ -478,14 +489,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
478489
}
479490
withNoErrors(singletonPath.cast(mirrorType).withSpan(span))
480491
case MirrorSource.GenericTuple(tps) =>
481-
val maxArity = Definitions.MaxTupleArity
482-
val arity = tps.size
483-
if tps.size <= maxArity then
484-
val tupleCls = defn.TupleType(arity).nn.classSymbol
485-
makeClassProductMirror(tupleCls.owner.reachableThisType, tupleCls, Some(tps))
486-
else
487-
val reason = s"it reduces to a tuple with arity $arity, expected arity <= $maxArity"
488-
withErrors(i"${defn.PairClass} is not a generic product because $reason")
492+
makeTupleProductMirror(tps)
489493
case MirrorSource.NamedTuple(nameTypePairs) =>
490494
makeNamedTupleProductMirror(nameTypePairs)
491495
case MirrorSource.ClassSymbol(pre, cls) =>
File renamed without changes.

tests/pos/i15398.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object i15398 {
2+
type Tuple23 = (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)
3+
4+
summon[Tuple.Size[Tuple23] =:= 23]
5+
val m = summon[scala.deriving.Mirror.Of[Tuple23]]
6+
summon[m.MirroredLabel =:= "Tuple23"]
7+
summon[m.MirroredElemTypes =:= Tuple23]
8+
summon[m.MirroredElemLabels =:= ("_1", "_2", "_3", "_4", "_5", "_6", "_7", "_8", "_9", "_10", "_11", "_12", "_13", "_14", "_15", "_16", "_17", "_18", "_19", "_20", "_21", "_22", "_23")]
9+
}

0 commit comments

Comments
 (0)