summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala13
-rw-r--r--test/files/run/null-and-intersect.check9
-rw-r--r--test/files/run/null-and-intersect.scala34
3 files changed, 54 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 915aba63db..2cf3d06866 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -1022,9 +1022,18 @@ abstract class Erasure extends AddInterfaces
Apply(Select(qual, cmpOp), List(gen.mkAttributedQualifier(targ.tpe)))
}
case RefinedType(parents, decls) if (parents.length >= 2) =>
- gen.evalOnce(qual, currentOwner, unit) { q =>
+ // Optimization: don't generate isInstanceOf tests if the static type
+ // conforms, because it always succeeds. (Or at least it had better.)
+ // At this writing the pattern matcher generates some instance tests
+ // involving intersections where at least one parent is statically known true.
+ // That needs fixing, but filtering the parents here adds an additional
+ // level of robustness (in addition to the short term fix.)
+ val parentTests = parents filterNot (qual.tpe <:< _)
+
+ if (parentTests.isEmpty) Literal(Constant(true))
+ else gen.evalOnce(qual, currentOwner, unit) { q =>
atPos(tree.pos) {
- parents map mkIsInstanceOf(q) reduceRight gen.mkAnd
+ parentTests map mkIsInstanceOf(q) reduceRight gen.mkAnd
}
}
case _ =>
diff --git a/test/files/run/null-and-intersect.check b/test/files/run/null-and-intersect.check
new file mode 100644
index 0000000000..81890cfeff
--- /dev/null
+++ b/test/files/run/null-and-intersect.check
@@ -0,0 +1,9 @@
+1
+2
+3
+4
+1
+2
+1
+2
+2
diff --git a/test/files/run/null-and-intersect.scala b/test/files/run/null-and-intersect.scala
new file mode 100644
index 0000000000..7266dabe6d
--- /dev/null
+++ b/test/files/run/null-and-intersect.scala
@@ -0,0 +1,34 @@
+object Test {
+ trait Immortal
+ class Bippy extends Immutable with Immortal
+ class Boppy extends Immutable
+
+ def f[T](x: Traversable[T]) = x match {
+ case _: Map[_, _] => 3
+ case _: Seq[_] => 2
+ case _: Iterable[_] => 1
+ case _ => 4
+ }
+ def g(x: Bippy) = x match {
+ case _: Immutable with Immortal => 1
+ case _ => 2
+ }
+ def h(x: Immutable) = x match {
+ case _: Immortal => 1
+ case _ => 2
+ }
+
+ def main(args: Array[String]): Unit = {
+ println(f(Set(1)))
+ println(f(Seq(1)))
+ println(f(Map(1 -> 2)))
+ println(f(null))
+
+ println(g(new Bippy))
+ println(g(null))
+
+ println(h(new Bippy))
+ println(h(new Boppy))
+ println(h(null))
+ }
+}