Skip to content

Commit 181fecc

Browse files
authored
Normalize tuple types in var args seq literals and classOf instances (#23465)
Fixes #22345.
2 parents 399f0f4 + a324d12 commit 181fecc

File tree

7 files changed

+25
-5
lines changed

7 files changed

+25
-5
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,17 @@ class TypeUtils:
152152
def namedTupleElementTypes(derived: Boolean)(using Context): List[(TermName, Type)] =
153153
namedTupleElementTypesUpTo(Int.MaxValue, derived)
154154

155+
/** If this is a generic tuple type with arity <= MaxTupleArity, return the
156+
* corresponding TupleN type, otherwise return this.
157+
*/
158+
def normalizedTupleType(using Context): Type =
159+
if self.isGenericTuple then
160+
self.tupleElementTypes match
161+
case Some(elems) if elems.size <= Definitions.MaxTupleArity => defn.tupleType(elems)
162+
case _ => self
163+
else
164+
self
165+
155166
def isNamedTupleType(using Context): Boolean = self match
156167
case defn.NamedTuple(_, _) => true
157168
case _ => false

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ trait Applications extends Compatibility {
942942
def makeVarArg(n: Int, elemFormal: Type): Unit = {
943943
val args = typedArgBuf.takeRight(n).toList
944944
typedArgBuf.dropRightInPlace(n)
945-
val elemtpt = TypeTree(elemFormal, inferred = true)
945+
val elemtpt = TypeTree(elemFormal.normalizedTupleType, inferred = true)
946946
typedArgBuf += seqToRepeated(SeqLiteral(args, elemtpt))
947947
}
948948

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
5353
if defn.SpecialClassTagClasses.contains(sym) then
5454
classTagModul.select(sym.name.toTermName).withSpan(span)
5555
else
56-
val ctype = escapeJavaArray(erasure(tp))
56+
val ctype = escapeJavaArray(erasure(tp.normalizedTupleType))
5757
if ctype.exists then
5858
classTagModul.select(nme.apply)
5959
.appliedToType(tp)

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -847,10 +847,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
847847
// Otherwise, map combinations of A *: B *: .... EmptyTuple with nesting levels <= 22
848848
// to the Tuple class of the right arity and select from that one
849849
def trySmallGenericTuple(qual: Tree, withCast: Boolean) =
850-
if qual.tpe.isSmallGenericTuple then
850+
val tp = qual.tpe.widenTermRefExpr
851+
val tpNormalized = tp.normalizedTupleType
852+
if tp ne tpNormalized then
851853
if withCast then
852-
val elems = qual.tpe.widenTermRefExpr.tupleElementTypes.getOrElse(Nil)
853-
typedSelectWithAdapt(tree, pt, qual.cast(defn.tupleType(elems)))
854+
typedSelectWithAdapt(tree, pt, qual.cast(tpNormalized))
854855
else
855856
typedSelectWithAdapt(tree, pt, qual)
856857
else EmptyTree

tests/run/i22345.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@main def Test: Unit =
2+
val a: Array[(Int, String)] = Array[Int *: String *: EmptyTuple]()

tests/run/i22345b.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@main def Test: Unit =
2+
val a: Array[(Int, String)] = Array[Int *: String *: EmptyTuple]((1, "hello"))

tests/run/i22345c.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
def makeSeq[T](args: T*): Seq[T] = args
2+
3+
@main def Test: Unit =
4+
val a: Array[(Int, String)] = makeSeq[Int *: String *: EmptyTuple]().toArray

0 commit comments

Comments
 (0)