Skip to content

Commit 094c9ec

Browse files
committed
Fix #9056: Erase tuple type tests to custom checks
1 parent bc8ae4c commit 094c9ec

File tree

4 files changed

+51
-1
lines changed

4 files changed

+51
-1
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,10 @@ class Definitions {
769769
lazy val RuntimeTuple_concat: Symbol = RuntimeTupleModule.requiredMethod("concat")
770770
lazy val RuntimeTuple_toArray: Symbol = RuntimeTupleModule.requiredMethod("toArray")
771771
lazy val RuntimeTuple_productToArray: Symbol = RuntimeTupleModule.requiredMethod("productToArray")
772+
lazy val RuntimeTuple_isInstanceOfTuple: Symbol = RuntimeTupleModule.requiredMethod("isInstanceOfTuple")
773+
lazy val RuntimeTuple_isInstanceOfEmptyTuple: Symbol = RuntimeTupleModule.requiredMethod("isInstanceOfEmptyTuple")
774+
lazy val RuntimeTuple_isInstanceOfNonEmptyTuple: Symbol = RuntimeTupleModule.requiredMethod("isInstanceOfNonEmptyTuple")
775+
lazy val RuntimeTuple_isInstanceOfPair: Symbol = RuntimeTupleModule.requiredMethod("isInstanceOfPair")
772776

773777
@tu lazy val TupledFunctionTypeRef: TypeRef = ctx.requiredClassRef("scala.TupledFunction")
774778
def TupledFunctionClass(implicit ctx: Context): ClassSymbol = TupledFunctionTypeRef.symbol.asClass

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ object TypeTestsCasts {
302302
*
303303
* expr.isInstanceOf[A | B] ~~> expr.isInstanceOf[A] | expr.isInstanceOf[B]
304304
* expr.isInstanceOf[A & B] ~~> expr.isInstanceOf[A] & expr.isInstanceOf[B]
305+
* expr.isInstanceOf[Tuple] ~~> scala.runtime.Tuple.isInstanceOfTuple(expr)
306+
* expr.isInstanceOf[EmptyTuple] ~~> scala.runtime.Tuple.isInstanceOfEmptyTuple(expr)
307+
* expr.isInstanceOf[NonEmptyTuple] ~~> scala.runtime.Tuple.isInstanceOfNonEmptyTuple(expr)
308+
* expr.isInstanceOf[*:[_, _]] ~~> scala.runtime.Tuple.isInstanceOfPair(expr)
305309
*
306310
* The transform happens before erasure of `testType`, thus cannot be merged
307311
* with `transformIsInstanceOf`, which depends on erased type of `testType`.
@@ -327,6 +331,14 @@ object TypeTestsCasts {
327331
derivedTree(e, defn.Any_isInstanceOf, e.tpe)
328332
.and(isArrayTest(e))
329333
}
334+
case tref: TypeRef if tref.symbol == defn.TupleClass =>
335+
ref(defn.RuntimeTuple_isInstanceOfTuple).appliedTo(expr)
336+
case tref: TypeRef if tref.symbol == defn.EmptyTupleClass =>
337+
ref(defn.RuntimeTuple_isInstanceOfEmptyTuple).appliedTo(expr)
338+
case tref: TypeRef if tref.symbol == defn.NonEmptyTupleClass =>
339+
ref(defn.RuntimeTuple_isInstanceOfNonEmptyTuple).appliedTo(expr)
340+
case AppliedType(tref: TypeRef, _) if tref.symbol == defn.PairClass =>
341+
ref(defn.RuntimeTuple_isInstanceOfPair).appliedTo(expr)
330342
case _ =>
331343
transformIsInstanceOf(expr, erasure(testType), flagUnrelated)
332344
}

library/src-bootstrapped/scala/runtime/Tuple.scala

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,4 +463,38 @@ object Tuple {
463463
def concatIterator(tup1: Tuple, tup2: Tuple): Iterator[Any] =
464464
tup1.asInstanceOf[Product].productIterator ++ tup2.asInstanceOf[Product].productIterator
465465

466+
def isInstanceOfTuple(x: Any): Boolean =
467+
x.isInstanceOf[Product] && isInstanceOfEmptyTuple(x) || isInstanceOfNonEmptyTuple(x)
468+
469+
def isInstanceOfEmptyTuple(x: Any): Boolean = x == Tuple0
470+
471+
def isInstanceOfNonEmptyTuple(x: Any): Boolean = isInstanceOfPair(x)
472+
473+
def isInstanceOfPair(x: Any): Boolean =
474+
x.isInstanceOf[Product] && (
475+
x.isInstanceOf[Tuple1[_]]
476+
|| x.isInstanceOf[Tuple2[_, _]]
477+
|| x.isInstanceOf[Tuple3[_, _, _]]
478+
|| x.isInstanceOf[Tuple4[_, _, _, _]]
479+
|| x.isInstanceOf[Tuple5[_, _, _, _, _]]
480+
|| x.isInstanceOf[Tuple6[_, _, _, _, _, _]]
481+
|| x.isInstanceOf[Tuple7[_, _, _, _, _, _, _]]
482+
|| x.isInstanceOf[Tuple8[_, _, _, _, _, _, _, _]]
483+
|| x.isInstanceOf[Tuple9[_, _, _, _, _, _, _, _, _]]
484+
|| x.isInstanceOf[Tuple10[_, _, _, _, _, _, _, _, _, _]]
485+
|| x.isInstanceOf[Tuple11[_, _, _, _, _, _, _, _, _, _, _]]
486+
|| x.isInstanceOf[Tuple12[_, _, _, _, _, _, _, _, _, _, _, _]]
487+
|| x.isInstanceOf[Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _]]
488+
|| x.isInstanceOf[Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _]]
489+
|| x.isInstanceOf[Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
490+
|| x.isInstanceOf[Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
491+
|| x.isInstanceOf[Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
492+
|| x.isInstanceOf[Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
493+
|| x.isInstanceOf[Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
494+
|| x.isInstanceOf[Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
495+
|| x.isInstanceOf[Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
496+
|| x.isInstanceOf[Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
497+
|| x.isInstanceOf[TupleXXL]
498+
)
499+
466500
}

tests/run/i9056.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
@main def Test =
3-
assert(((): Any).isInstanceOf[Tuple])
3+
((): Any).isInstanceOf[Tuple]
44
assert((1, 2).isInstanceOf[Tuple])
55
assert((1, 2, 3).isInstanceOf[Tuple])
66
assert(!"".isInstanceOf[Tuple])

0 commit comments

Comments
 (0)