From 7458941e2c3d51b5c42167cb65e36d8f4d93e594 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 25 Sep 2024 16:43:07 +0100 Subject: [PATCH 1/3] Avoid erasure/preErasure issues around Any in transformIsInstanceOf The testType Any is erased to Object, but the expr type Int isn't erased to Integer, so then it fails as Int !<: Object. We avoid the problem by feeding in AnyVal, leading to a (possibly elided) non-null test only. [Cherry-picked d02d4b86dfe281cca18760d49f026a2a9b332e53] --- .../src/dotty/tools/dotc/transform/TypeTestsCasts.scala | 6 +++++- tests/pos/i21544.scala | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i21544.scala diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 8223c60aab5f..7027ca9dd913 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -352,7 +352,11 @@ object TypeTestsCasts { report.error(em"$untestable cannot be used in runtime type tests", tree.srcPos) constant(expr, Literal(Constant(false))) case _ => - val erasedTestType = erasure(testType) + val erasedTestType = + if testType.isAny && expr.tpe.isPrimitiveValueType then + defn.AnyValType + else + erasure(testType) transformIsInstanceOf(expr, erasedTestType, erasedTestType, flagUnrelated) } diff --git a/tests/pos/i21544.scala b/tests/pos/i21544.scala new file mode 100644 index 000000000000..45da101e7490 --- /dev/null +++ b/tests/pos/i21544.scala @@ -0,0 +1,2 @@ +class Test(): + def m1(xs: List[Boolean]) = for (x: Any) <- xs yield x From e463cce4a301b74ac40091ee0f135cebbd2334df Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 30 Oct 2024 14:04:44 +0000 Subject: [PATCH 2/3] Simplify transformIsInstanceOf check [Cherry-picked 7b721f0fdc032e871737d11ed1841c9fdc4ef98d] --- .../src/dotty/tools/dotc/transform/TypeTestsCasts.scala | 9 +++------ tests/pos/i21544.scala | 2 ++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 7027ca9dd913..5a7fb258f4eb 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -250,7 +250,8 @@ object TypeTestsCasts { else foundClasses.exists(check) end checkSensical - if (expr.tpe <:< testType) && inMatch then + val tp = if expr.tpe.isPrimitiveValueType then defn.boxedType(expr.tpe) else expr.tpe + if tp <:< testType && inMatch then if expr.tpe.isNotNull then constant(expr, Literal(Constant(true))) else expr.testNotNull else { @@ -352,11 +353,7 @@ object TypeTestsCasts { report.error(em"$untestable cannot be used in runtime type tests", tree.srcPos) constant(expr, Literal(Constant(false))) case _ => - val erasedTestType = - if testType.isAny && expr.tpe.isPrimitiveValueType then - defn.AnyValType - else - erasure(testType) + val erasedTestType = erasure(testType) transformIsInstanceOf(expr, erasedTestType, erasedTestType, flagUnrelated) } diff --git a/tests/pos/i21544.scala b/tests/pos/i21544.scala index 45da101e7490..08a3911e4412 100644 --- a/tests/pos/i21544.scala +++ b/tests/pos/i21544.scala @@ -1,2 +1,4 @@ class Test(): def m1(xs: List[Boolean]) = for (x: Any) <- xs yield x + def m2(xs: List[Boolean]) = for (x: AnyVal) <- xs yield x + def m3(xs: List[Boolean]) = for (x: Matchable) <- xs yield x From f7a54b07ef2af59d0aa15654a776435aab04c9f3 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sat, 2 Nov 2024 18:09:27 +0000 Subject: [PATCH 3/3] Add extra isInstanceOf test cases [Cherry-picked 49d876a87851b78a63f3027811b41791a2fe583c] --- tests/pos/i21544.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/pos/i21544.scala b/tests/pos/i21544.scala index 08a3911e4412..b2d978ea7d02 100644 --- a/tests/pos/i21544.scala +++ b/tests/pos/i21544.scala @@ -2,3 +2,12 @@ class Test(): def m1(xs: List[Boolean]) = for (x: Any) <- xs yield x def m2(xs: List[Boolean]) = for (x: AnyVal) <- xs yield x def m3(xs: List[Boolean]) = for (x: Matchable) <- xs yield x + + def v1(xs: List[AnyVal]) = for (x: Any) <- xs yield x + def v2(xs: List[AnyVal]) = for (x: AnyVal) <- xs yield x + def v3(xs: List[AnyVal]) = for (x: Matchable) <- xs yield x + + def t1(xs: List[Matchable]) = for (x: Any) <- xs yield x + def t2(xs: List[Matchable]) = for (x: Matchable) <- xs yield x + + def a1(xs: List[Any]) = for (x: Any) <- xs yield x