Skip to content

Commit 3f3a05c

Browse files
committed
Equate TupleN(...) and *: types
Make `T1 *: ... *: Tn *: Unit` a subtype of `(T1, ..., Tn)`. This is sound since the two types are erased to the same representation. I tried alternatively to (...) types to `*:` types instead of `Tuple` types. But then we have to translate `TupleN` classes as well since these can come from Scala-2. This looked more fragile than the solution in this commit.
1 parent 0e436f3 commit 3f3a05c

File tree

4 files changed

+26
-18
lines changed

4 files changed

+26
-18
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import config.Printers.{typr, constr, subtyping, gadts, noPrinter}
1212
import TypeErasure.{erasedLub, erasedGlb}
1313
import TypeApplications._
1414
import Constants.Constant
15+
import transform.TypeUtils._
1516
import scala.util.control.NonFatal
1617
import typer.ProtoTypes.constrained
1718
import reporting.trace
@@ -847,6 +848,8 @@ class TypeComparer(initctx: Context) extends ConstraintHandling {
847848
case info2: TypeBounds =>
848849
compareLower(info2, tyconIsTypeRef = true)
849850
case info2: ClassInfo =>
851+
tycon2.name.toString.startsWith("Tuple") &&
852+
defn.isTupleType(tp2) && isSubType(tp1, tp2.toNestedPairs) ||
850853
tryBaseType(info2.cls)
851854
case _ =>
852855
fourthTry

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import TypeApplications._
2424
import Decorators._
2525
import config.Config
2626
import util.Positions._
27-
import dotty.tools.dotc.transform.SymUtils._
27+
import transform.SymUtils._
28+
import transform.TypeUtils._
2829
import dotty.tools.dotc.transform.FirstTransform
2930

3031
import scala.annotation.switch
@@ -176,11 +177,11 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
176177
}
177178

178179
homogenize(tp) match {
179-
case AppliedType(tycon, args) =>
180+
case tp @ AppliedType(tycon, args) =>
180181
val cls = tycon.typeSymbol
181182
if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*"
182183
if (defn.isFunctionClass(cls)) return toTextFunction(args, cls.name.isImplicitFunction, cls.name.isErasedFunction)
183-
if (defn.isTupleClass(cls)) return toTextTuple(args)
184+
if (tp.tupleArity >= 2) return toTextTuple(tp.tupleElementTypes)
184185
if (isInfixType(tp)) {
185186
val l :: r :: Nil = args
186187
val opName = tyconName(tycon)

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

+4
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,9 @@ object TypeUtils {
5050
else if (defn.isTupleClass(tp1.classSymbol)) tp1.dealias.argInfos
5151
else throw new AssertionError("not a tuple")
5252
}
53+
54+
/** The `*:` equivalent of an instantce of a Tuple class */
55+
def toNestedPairs(implicit ctx: Context): Type =
56+
(tupleElementTypes :\ (defn.UnitType: Type))(defn.PairType.appliedTo(_, _))
5357
}
5458
}

tests/run/tuples1.scala

+15-15
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ object Test extends App {
1414
val h8 = x8.head; val h8c: String = h8; println(s"h8 = $h8")
1515
val t1 = x1.tail; val t1c: Unit = t1; println(s"t1 = $t1")
1616
val t2 = x2.tail; val t2c: Int *: Unit = t2; println(s"t2 = $t2")
17-
val t7 = x7.tail; val t7c: String *: Int *: Unit = t7.tail.tail.tail.tail; println(s"t7 = $t7")
17+
val t7 = x7.tail; val t7c: (String, Int) = t7.tail.tail.tail.tail; println(s"t7 = $t7")
1818
val t8 = x8.tail; val t8c: Int = t8(6); println(s"t8 = $t8")
1919
val a1_0 = x1(0); val a1_0c: Int = a1_0; println(s"a1_0 = $a1_0")
2020
val a2_0 = x2(0); val a2_0c: String = a2_0; println(s"a2_0 = $a2_0")
@@ -25,14 +25,14 @@ object Test extends App {
2525
val c0_0 = x0 ++ x0; val c0_0c: Unit = c0_0; println(s"c0_0 = $c0_0")
2626
val c0_1 = x0 ++ x1; val c0_1c: Int *: Unit = c0_1c; println(s"c0_1 = $c0_1")
2727
val c1_0 = x1 ++ x0; val c1_0c: Int *: Unit = c1_0c; println(s"c1_0 = $c1_0")
28-
val c0_4 = x0 ++ x4; val c0_4c: String *: Int *: String *: Int *: Unit = c0_4; println(s"c0_4 = $c0_4")
29-
val c4_0 = x4 ++ x0; val c4_0c: String *: Int *: String *: Int *: Unit = c4_0; println(s"c4_0 = $c4_0")
30-
val c1_1 = x1 ++ x1; val c1_1c: Int *: Int *: Unit = c1_1; println(s"c1_1 = $c1_1")
31-
val c1_8 = x1 ++ x8; val c1_8c: Int *: String *: Int *: String *: Int *: String *: Int *: String *: Int *: Unit = c1_8; println(s"c1_8 = $c1_8")
32-
val c2_1 = x2 ++ x1; val c2_1c: String *: Int *: Int *: Unit = c2_1; println(s"c2_1 = $c2_1")
33-
val c2_2 = x2 ++ x2; val c2_2c: String *: Int *: String *: Int *: Unit = c2_2; println(s"c2_2 = $c2_2")
34-
val c2_3 = x2 ++ x3; val c2_3c: String *: Int *: Int *: String *: Int *: Unit = c2_3; println(s"c2_3 = $c2_3")
35-
val c3_3 = x3 ++ x3; val c3_3c: Int *: String *: Int *: Int *: String *: Int *: Unit = c3_3; println(s"c3_3 = $c3_3")
28+
val c0_4 = x0 ++ x4; val c0_4c: (String, Int, String, Int) = c0_4; println(s"c0_4 = $c0_4")
29+
val c4_0 = x4 ++ x0; val c4_0c: (String, Int, String, Int) = c4_0; println(s"c4_0 = $c4_0")
30+
val c1_1 = x1 ++ x1; val c1_1c: (Int, Int) = c1_1; println(s"c1_1 = $c1_1")
31+
val c1_8 = x1 ++ x8; val c1_8c: (Int, String, Int, String, Int, String, Int, String, Int) = c1_8; println(s"c1_8 = $c1_8")
32+
val c2_1 = x2 ++ x1; val c2_1c: (String, Int, Int) = c2_1; println(s"c2_1 = $c2_1")
33+
val c2_2 = x2 ++ x2; val c2_2c: (String, Int, String, Int) = c2_2; println(s"c2_2 = $c2_2")
34+
val c2_3 = x2 ++ x3; val c2_3c: (String, Int, Int, String, Int) = c2_3; println(s"c2_3 = $c2_3")
35+
val c3_3 = x3 ++ x3; val c3_3c: (Int, String, Int, Int, String, Int) = c3_3; println(s"c3_3 = $c3_3")
3636

3737
val x23 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23)
3838
type T23 = (Int, Int, Int, Int, Int,
@@ -102,12 +102,12 @@ object Test extends App {
102102

103103
def concat[X <: Tuple, Y <: Tuple](x: X, y: Y): Tuple.Concat[X, Y] = x ++ y
104104
def concat0(x: Tuple, y: Tuple): Tuple.Concat[x.type, y.type] = x ++ y
105-
val conc1: String *: Int *: Unit = concat((), tl1)
106-
val conc2: String *: Int *: Unit = concat(tl1, ())
107-
val conc3: String *: Int *: String *: Int *: Unit = concat(tl1, tl1)
108-
val conc4: String *: Int *: Unit = concat0((), tl1)
109-
val conc5: String *: Int *: Unit = concat0(tl1, ())
110-
val conc6: String *: Int *: String *: Int *: Unit = concat0(tl1, tl1)
105+
val conc1: (String, Int) = concat((), tl1)
106+
val conc2: (String, Int) = concat(tl1, ())
107+
val conc3: (String, Int, String, Int) = concat(tl1, tl1)
108+
val conc4: (String, Int) = concat0((), tl1)
109+
val conc5: (String, Int) = concat0(tl1, ())
110+
val conc6: (String, Int, String, Int) = concat0(tl1, tl1)
111111

112112
def size[X <: Tuple](x: X): Tuple.Size[X] = x.size
113113
def size0(x: Tuple): Tuple.Size[x.type] = x.size

0 commit comments

Comments
 (0)