Skip to content

Commit e79314d

Browse files
authored
Merge pull request #486 from scala/backport-lts-3.3-23465
Backport "Normalize tuple types in var args seq literals and classOf instances" to 3.3 LTS
2 parents 62387f9 + ba5021a commit e79314d

File tree

7 files changed

+24
-5
lines changed

7 files changed

+24
-5
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,16 @@ class TypeUtils:
115115
case Some(types) => TypeOps.nestedPairs(types)
116116
case None => throw new AssertionError("not a tuple")
117117

118+
/** If this is a generic tuple type with arity <= MaxTupleArity, return the
119+
* corresponding TupleN type, otherwise return this.
120+
*/
121+
def normalizedTupleType(using Context): Type =
122+
if self.isGenericTuple then
123+
self.tupleElementTypes match
124+
case Some(elems) if elems.size <= Definitions.MaxTupleArity => defn.tupleType(elems)
125+
case _ => self
126+
else
127+
self
118128
def refinedWith(name: Name, info: Type)(using Context) = RefinedType(self, name, info)
119129

120130
/** Is this type a methodic type that takes at least one parameter? */

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ trait Applications extends Compatibility {
841841
def makeVarArg(n: Int, elemFormal: Type): Unit = {
842842
val args = typedArgBuf.takeRight(n).toList
843843
typedArgBuf.dropRightInPlace(n)
844-
val elemtpt = TypeTree(elemFormal)
844+
val elemtpt = TypeTree(elemFormal.normalizedTupleType)
845845
typedArgBuf += seqToRepeated(SeqLiteral(args, elemtpt))
846846
}
847847

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

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

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -738,10 +738,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
738738
// Otherwise, map combinations of A *: B *: .... EmptyTuple with nesting levels <= 22
739739
// to the Tuple class of the right arity and select from that one
740740
def trySmallGenericTuple(qual: Tree, withCast: Boolean) =
741-
if qual.tpe.isSmallGenericTuple then
741+
val tp = qual.tpe.widenTermRefExpr
742+
val tpNormalized = tp.normalizedTupleType
743+
if tp ne tpNormalized then
742744
if withCast then
743-
val elems = qual.tpe.widenTermRefExpr.tupleElementTypes.getOrElse(Nil)
744-
typedSelectWithAdapt(tree, pt, qual.cast(defn.tupleType(elems)))
745+
typedSelectWithAdapt(tree, pt, qual.cast(tpNormalized))
745746
else
746747
typedSelectWithAdapt(tree, pt, qual)
747748
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)