summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-09-28 15:43:01 +0000
committerPaul Phillips <paulp@improving.org>2010-09-28 15:43:01 +0000
commitc18c3e108131bbfd6d2c4bbc3395c3a7f76a581b (patch)
treede790f7df6ca1923df51f28b9ad7a53a9c72740b /src
parentfda537c771e16655e268e5c006f2dead25aeda30 (diff)
downloadscala-c18c3e108131bbfd6d2c4bbc3395c3a7f76a581b.tar.gz
scala-c18c3e108131bbfd6d2c4bbc3395c3a7f76a581b.tar.bz2
scala-c18c3e108131bbfd6d2c4bbc3395c3a7f76a581b.zip
A little reorganization of some pattern matcher...
A little reorganization of some pattern matcher logic. I must have a short memory to even consider touching it, but maybe I'm still infused with the mario invulnerability star one receives after some time spent consulting with martin. No review.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala75
2 files changed, 37 insertions, 40 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 93eaa9123f..df1e604081 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1109,7 +1109,7 @@ abstract class GenICode extends SubComponent {
ctx
case _ =>
- abort("Unexpected tree in genLoad: " + tree + " at: " + tree.pos)
+ abort("Unexpected tree in genLoad: " + tree + "/" + tree.getClass + " at: " + tree.pos)
}
// emit conversion
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index eb3774b0b5..d6ad521310 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -613,22 +613,12 @@ trait ParallelMatching extends ast.TreeDSL
val subsumed = yeses map (x => (x.bx, x.subsumed))
val remaining = noes map (x => (x.bx, x.remaining))
- // temporary checks so we're less crashy while we determine what to implement.
- def checkErroneous(scrut: Scrutinee): Type = {
- scrut.tpe match {
- case ThisType(clazz) if clazz.isAnonymousClass =>
- cunit.error(scrut.pos, "self type test in anonymous class forbidden by implementation.")
- ErrorType
- case x => x
- }
- }
-
private def mkZipped =
for (Yes(j, moreSpecific, subsumed) <- yeses) yield
j -> (moreSpecific :: subsumed)
lazy val casted = scrut castedTo pmatch.headType
- lazy val cond = condition(checkErroneous(casted).tpe, scrut, head.boundVariables.nonEmpty)
+ lazy val cond = condition(casted.tpe, scrut, head.boundVariables.nonEmpty)
private def isAnyMoreSpecific = yeses exists (x => !x.moreSpecific.isEmpty)
lazy val (subtests, subtestVars) =
@@ -873,36 +863,43 @@ trait ParallelMatching extends ast.TreeDSL
final def condition(tpe: Type, scrutTree: Tree, isBound: Boolean): Tree = {
assert((tpe ne NoType) && (scrutTree.tpe ne NoType))
- def useEqTest = tpe.termSymbol.isModule || (tpe.prefix eq NoPrefix)
+ def isMatchUnlessNull = scrutTree.tpe <:< tpe && tpe.isAnyRef
+ def isRef = scrutTree.tpe.isAnyRef
+
+ // See ticket #1503 for the motivation behind checking for a binding.
+ // The upshot is that it is unsound to assume equality means the right
+ // type, but if the value doesn't appear on the right hand side of the
+ // match that's unimportant; so we add an instance check only if there
+ // is a binding.
+ def bindingWarning() = {
+ if (isBound && settings.Xmigration28.value) {
+ cunit.warning(scrutTree.pos,
+ "A bound pattern such as 'x @ Pattern' now matches fewer cases than the same pattern with no binding.")
+ }
+ }
- // case SingleType(_, _) | ThisType(_) | SuperType(_, _) =>
- // val cmpOp = if (targ.tpe <:< AnyValClass.tpe) Any_equals else Object_eq
- // Apply(Select(qual, cmpOp), List(gen.mkAttributedQualifier(targ.tpe)))
+ def genEquals(sym: Symbol): Tree = {
+ val t1: Tree = REF(sym) MEMBER_== scrutTree
- typer typed (tpe match {
- case ct: ConstantType => ct.value match {
- case v @ Constant(null) if scrutTree.tpe.isAnyRef => scrutTree OBJ_EQ NULL
- case v => scrutTree MEMBER_== Literal(v)
- }
- case _: SingletonType if useEqTest =>
- val eqTest = REF(tpe.termSymbol) MEMBER_== scrutTree
-
- // See ticket #1503 for the motivation behind checking for a binding.
- // The upshot is that it is unsound to assume equality means the right
- // type, but if the value doesn't appear on the right hand side of the
- // match that's unimportant; so we add an instance check only if there
- // is a binding.
- if (isBound) {
- if (settings.Xmigration28.value) {
- cunit.warning(scrutTree.pos, "A bound pattern such as 'x @ Pattern' now matches fewer cases than the same pattern with no binding.")
- }
- eqTest AND (scrutTree IS tpe.widen)
- }
- else eqTest
-
- case _ if scrutTree.tpe <:< tpe && tpe.isAnyRef => scrutTree OBJ_!= NULL
- case _ => scrutTree IS tpe
- })
+ if (isBound) {
+ bindingWarning()
+ t1 AND (scrutTree IS tpe.widen)
+ }
+ else t1
+ }
+
+ typer typed {
+ tpe match {
+ case ConstantType(Constant(null)) if isRef => scrutTree OBJ_EQ NULL
+ case ConstantType(Constant(value)) => scrutTree MEMBER_== Literal(value)
+ case SingleType(NoPrefix, sym) => genEquals(sym)
+ case SingleType(pre, sym) if sym.isModule => genEquals(sym)
+ case ThisType(sym) if sym.isAnonymousClass => cunit.error(sym.pos, "self type test in anonymous class forbidden by implementation.") ; EmptyTree
+ case ThisType(sym) if sym.isModule => genEquals(sym)
+ case _ if isMatchUnlessNull => scrutTree OBJ_NE NULL
+ case _ => scrutTree IS tpe
+ }
+ }
}
/** adds a test comparing the dynamic outer to the static outer */