aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/transform/TypeTestsCasts.scala31
-rw-r--r--tests/run/i1354.check6
-rw-r--r--tests/run/i1354.scala27
3 files changed, 56 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
index c57d6fd1a..6de2bf44c 100644
--- a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
+++ b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
@@ -1,16 +1,12 @@
package dotty.tools.dotc
package transform
-import TreeTransforms._
-import core.Denotations._
-import core.SymDenotations._
import core.Contexts._
import core.Symbols._
import core.Types._
import core.Constants._
import core.StdNames._
import core.TypeErasure.isUnboundedGeneric
-import typer.ErrorReporting._
import ast.Trees._
import Erasure.Boxing._
import core.TypeErasure._
@@ -92,14 +88,33 @@ trait TypeTestsCasts {
unbox(qual.ensureConforms(defn.ObjectType), argType)
else if (isDerivedValueClass(argCls)) {
qual // adaptToType in Erasure will do the necessary type adaptation
- } else
+ }
+ else
derivedTree(qual, defn.Any_asInstanceOf, argType)
}
- def erasedArg = erasure(tree.args.head.tpe)
+
+ /** Transform isInstanceOf OrType
+ *
+ * expr.isInstanceOf[A | B] ~~> expr.isInstanceOf[A] | expr.isInstanceOf[B]
+ *
+ * The transform happens before erasure of `argType`, thus cannot be merged
+ * with `transformIsInstanceOf`, which depends on erased type of `argType`.
+ */
+ def transformOrTypeTest(qual: Tree, argType: Type): Tree = argType match {
+ case OrType(tp1, tp2) =>
+ evalOnce(qual) { fun =>
+ transformOrTypeTest(fun, tp1)
+ .select(nme.OR)
+ .appliedTo(transformOrTypeTest(fun, tp2))
+ }
+ case _ =>
+ transformIsInstanceOf(qual, erasure(argType))
+ }
+
if (sym eq defn.Any_isInstanceOf)
- transformIsInstanceOf(qual, erasedArg)
+ transformOrTypeTest(qual, tree.args.head.tpe)
else if (sym eq defn.Any_asInstanceOf)
- transformAsInstanceOf(erasedArg)
+ transformAsInstanceOf(erasure(tree.args.head.tpe))
else tree
case _ =>
diff --git a/tests/run/i1354.check b/tests/run/i1354.check
new file mode 100644
index 000000000..ce686866d
--- /dev/null
+++ b/tests/run/i1354.check
@@ -0,0 +1,6 @@
+0
+false
+5
+1
+true
+true
diff --git a/tests/run/i1354.scala b/tests/run/i1354.scala
new file mode 100644
index 000000000..08b129e4e
--- /dev/null
+++ b/tests/run/i1354.scala
@@ -0,0 +1,27 @@
+object Test {
+ def foo(a: Int | Double) = a match {
+ case a: (Float | Boolean) => 1
+ case _ => 0
+ }
+
+ def typeTest(a: Int | Double) = a.isInstanceOf[Float | Boolean] // false
+
+ def typeCast(a: Int | Double) = a.asInstanceOf[Float | Boolean] // no error
+
+ def main(args: Array[String]): Unit = {
+ println(foo(4))
+
+ println(typeTest(4))
+
+ println(typeCast(5))
+
+ Boolean.box(true) match {
+ case a: (Float | Boolean) => println(1)
+ case _ => println(0)
+ }
+
+ println(Boolean.box(true).isInstanceOf[Float | Boolean])
+
+ println(Boolean.box(true).asInstanceOf[Float | Boolean])
+ }
+}