Skip to content

Commit c96d093

Browse files
oderskynicolasstucki
authored andcommitted
Improve treatment of tuples
1 parent 21b1aaa commit c96d093

File tree

7 files changed

+27
-16
lines changed

7 files changed

+27
-16
lines changed

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,7 +1170,9 @@ class Definitions {
11701170
}
11711171

11721172
def tupleType(elems: List[Type]): Type = {
1173-
TupleType(elems.size).appliedTo(elems)
1173+
val arity = elems.length
1174+
if (arity <= MaxTupleArity && TupleType(arity) != null) TupleType(arity).appliedTo(elems)
1175+
else TypeOps.nestedPairs(elems)
11741176
}
11751177

11761178
def isProductSubType(tp: Type)(implicit ctx: Context): Boolean =
@@ -1263,8 +1265,9 @@ class Definitions {
12631265
def adjustForTuple(cls: ClassSymbol, tparams: List[TypeSymbol], parents: List[Type]): List[Type] = {
12641266
def syntheticParent(tparams: List[TypeSymbol]): Type =
12651267
if (tparams.isEmpty) TupleTypeRef
1266-
else (tparams :\ (UnitType: Type)) ((tparam, tail) => PairType.appliedTo(tparam.typeRef, tail))
1267-
if (isTupleClass(cls) || cls == UnitClass) parents :+ syntheticParent(tparams) else parents
1268+
else TypeOps.nestedPairs(tparams.map(_.typeRef))
1269+
if (isTupleClass(cls) || cls == UnitClass) parents :+ syntheticParent(tparams)
1270+
else parents
12681271
}
12691272

12701273
// ----- primitive value class machinery ------------------------------------------

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,6 @@ object TypeOps {
570570

571571
// TODO: Move other typeops here. It's a bit weird that they are a part of `ctx`
572572

573-
def tupleOf(ts: List[Type])(implicit ctx: Context): Type =
573+
def nestedPairs(ts: List[Type])(implicit ctx: Context): Type =
574574
(ts :\ (defn.UnitType: Type))(defn.PairType.appliedTo(_, _))
575575
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
179179
val cls = tycon.typeSymbol
180180
if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*"
181181
if (defn.isFunctionClass(cls)) return toTextFunction(args, cls.name.isImplicitFunction, cls.name.isErasedFunction)
182-
if (tp.tupleArity >= 2) return toTextTuple(tp.tupleElementTypes)
182+
if (tp.tupleArity >= 2 && !ctx.settings.YprintDebug.value) return toTextTuple(tp.tupleElementTypes)
183183
if (isInfixType(tp)) {
184184
val l :: r :: Nil = args
185185
val opName = tyconName(tycon)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,6 @@ object TypeUtils {
5050

5151
/** The `*:` equivalent of an instance of a Tuple class */
5252
def toNestedPairs(implicit ctx: Context): Type =
53-
TypeOps.tupleOf(tupleElementTypes)
53+
TypeOps.nestedPairs(tupleElementTypes)
5454
}
5555
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ trait Deriving { this: Typer =>
7878
case _ =>
7979
(sym.termRef, Nil)
8080
}
81-
val elemShape = TypeOps.tupleOf(elems)
81+
val elemShape = TypeOps.nestedPairs(elems)
8282
defn.ShapeCaseType.appliedTo(constr, elemShape)
8383
}
8484

8585
/** The shape of `cls` if `cls` is sealed */
8686
private def sealedShape: Type = {
8787
val cases = children.map(caseShape).filter(_.exists)
88-
val casesShape = TypeOps.tupleOf(cases)
88+
val casesShape = TypeOps.nestedPairs(cases)
8989
defn.ShapeCasesType.appliedTo(casesShape)
9090
}
9191

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,7 +1919,7 @@ class Typer extends Namer
19191919
else {
19201920
val elemTpes = (elems, pts).zipped.map((elem, pt) =>
19211921
ctx.typeComparer.widenInferred(elem.tpe, pt))
1922-
val resTpe = TypeOps.tupleOf(elemTpes)
1922+
val resTpe = TypeOps.nestedPairs(elemTpes)
19231923
app1.cast(resTpe)
19241924
}
19251925
}
@@ -1942,13 +1942,15 @@ class Typer extends Namer
19421942
val quotedPt = if (exprPt.exists) exprPt.argTypesHi.head else defn.AnyType
19431943
val quoted1 = typedExpr(quoted, quotedPt)(quoteContext.addMode(Mode.QuotedPattern))
19441944
val (shape, splices) = splitQuotePattern(quoted1)
1945-
val splicePat = typed(untpd.Tuple(splices.map(untpd.TypedSplice(_))).withSpan(quoted.span))
1946-
val patType = TypeOps.tupleOf(splices.tpes.map(_.widen))
1945+
val patType = defn.tupleType(splices.tpes.map(_.widen))
1946+
val splicePat = typed(untpd.Tuple(splices.map(untpd.TypedSplice(_))).withSpan(quoted.span), patType)
19471947
UnApply(
1948-
ref(defn.QuotedMatcher_unapplyR).appliedToType(patType),
1949-
ref(defn.InternalQuoted_exprQuoteR).appliedToType(shape.tpe).appliedTo(shape) :: givenReflection :: Nil,
1950-
splicePat :: Nil,
1951-
pt)
1948+
fun = ref(defn.QuotedMatcher_unapplyR).appliedToType(patType),
1949+
implicits =
1950+
ref(defn.InternalQuoted_exprQuoteR).appliedToType(shape.tpe).appliedTo(shape) ::
1951+
givenReflection :: Nil,
1952+
patterns = splicePat :: Nil,
1953+
proto = pt)
19521954
}
19531955
else
19541956
typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprQuoteR), quoted), pt)(quoteContext).withSpan(tree.span)

tests/pos/quotedPatterns.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ object Test {
33
val x = '{1 + 2}
44

55
def f(x: Int) = x
6+
def g(x: Int, y: Int) = x * y
67

78
val res: quoted.Expr[Int] = x match {
89
case '{1 + 2} => '{0}
910
case '{f($y)} => y
10-
//case '{ 1 + ($y: Int)} => y // currently gives an unreachable case error
11+
case '{g($y, $z)} => '{$y * $z}
12+
case '{ 1 + ($y: Int)} => y
13+
// currently gives an unreachable case warning
14+
// but only when used in conjunction with the others.
15+
// I believe this is because implicit arguments are not taken
16+
// into account when checking whether we have already seen an `unapply` before.
1117
case _ => '{1}
1218
}
1319
}

0 commit comments

Comments
 (0)