Skip to content

Commit 5ffce6e

Browse files
authored
Merge pull request #1415 from dotty-staging/fix-i1354
fix #1354: improve type test of union types
2 parents fec3ec3 + 2542111 commit 5ffce6e

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

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

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
package dotty.tools.dotc
22
package transform
33

4-
import TreeTransforms._
5-
import core.Denotations._
6-
import core.SymDenotations._
74
import core.Contexts._
85
import core.Symbols._
96
import core.Types._
107
import core.Constants._
118
import core.StdNames._
129
import core.TypeErasure.isUnboundedGeneric
13-
import typer.ErrorReporting._
1410
import ast.Trees._
1511
import Erasure.Boxing._
1612
import core.TypeErasure._
@@ -92,14 +88,33 @@ trait TypeTestsCasts {
9288
unbox(qual.ensureConforms(defn.ObjectType), argType)
9389
else if (isDerivedValueClass(argCls)) {
9490
qual // adaptToType in Erasure will do the necessary type adaptation
95-
} else
91+
}
92+
else
9693
derivedTree(qual, defn.Any_asInstanceOf, argType)
9794
}
98-
def erasedArg = erasure(tree.args.head.tpe)
95+
96+
/** Transform isInstanceOf OrType
97+
*
98+
* expr.isInstanceOf[A | B] ~~> expr.isInstanceOf[A] | expr.isInstanceOf[B]
99+
*
100+
* The transform happens before erasure of `argType`, thus cannot be merged
101+
* with `transformIsInstanceOf`, which depends on erased type of `argType`.
102+
*/
103+
def transformOrTypeTest(qual: Tree, argType: Type): Tree = argType match {
104+
case OrType(tp1, tp2) =>
105+
evalOnce(qual) { fun =>
106+
transformOrTypeTest(fun, tp1)
107+
.select(nme.OR)
108+
.appliedTo(transformOrTypeTest(fun, tp2))
109+
}
110+
case _ =>
111+
transformIsInstanceOf(qual, erasure(argType))
112+
}
113+
99114
if (sym eq defn.Any_isInstanceOf)
100-
transformIsInstanceOf(qual, erasedArg)
115+
transformOrTypeTest(qual, tree.args.head.tpe)
101116
else if (sym eq defn.Any_asInstanceOf)
102-
transformAsInstanceOf(erasedArg)
117+
transformAsInstanceOf(erasure(tree.args.head.tpe))
103118
else tree
104119

105120
case _ =>

tests/run/i1354.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
0
2+
false
3+
5
4+
1
5+
true
6+
true

tests/run/i1354.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
object Test {
2+
def foo(a: Int | Double) = a match {
3+
case a: (Float | Boolean) => 1
4+
case _ => 0
5+
}
6+
7+
def typeTest(a: Int | Double) = a.isInstanceOf[Float | Boolean] // false
8+
9+
def typeCast(a: Int | Double) = a.asInstanceOf[Float | Boolean] // no error
10+
11+
def main(args: Array[String]): Unit = {
12+
println(foo(4))
13+
14+
println(typeTest(4))
15+
16+
println(typeCast(5))
17+
18+
Boolean.box(true) match {
19+
case a: (Float | Boolean) => println(1)
20+
case _ => println(0)
21+
}
22+
23+
println(Boolean.box(true).isInstanceOf[Float | Boolean])
24+
25+
println(Boolean.box(true).asInstanceOf[Float | Boolean])
26+
}
27+
}

0 commit comments

Comments
 (0)