diff options
author | Paul Phillips <paulp@improving.org> | 2011-06-07 18:06:34 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-06-07 18:06:34 +0000 |
commit | 5fa1978fac07e62570409c649faf3021b2709a18 (patch) | |
tree | 8b19cfb63beae7651d5edfa562d313aa489c3860 | |
parent | fec42c1f3a6753f962a03b22c4728f8f791dbb66 (diff) | |
download | scala-5fa1978fac07e62570409c649faf3021b2709a18.tar.gz scala-5fa1978fac07e62570409c649faf3021b2709a18.tar.bz2 scala-5fa1978fac07e62570409c649faf3021b2709a18.zip |
Modified erasure not to generate instance tests...
Modified erasure not to generate instance tests for statically known
types. It appears the production of types like "Foo with Bar" in the
pattern matcher (where the scrutinee is known to be Foo) has been a
major contributor of suboptimal pattern matches. I will also fix it in
the matcher, but it makes sense to catch it in erasure as both a check
on the matcher and because they may come from elsewhere too. Review by
odersky.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 13 | ||||
-rw-r--r-- | test/files/run/null-and-intersect.check | 9 | ||||
-rw-r--r-- | test/files/run/null-and-intersect.scala | 34 |
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)) + } +} |