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.

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@23125 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
extempore 2010-09-28 15:43:01 +00:00
parent 2adc29ea8b
commit dd752c9e33
2 changed files with 38 additions and 41 deletions

View File

@ -1109,7 +1109,7 @@ abstract class GenICode extends SubComponent {
ctx ctx
case _ => case _ =>
abort("Unexpected tree in genLoad: " + tree + " at: " + tree.pos) abort("Unexpected tree in genLoad: " + tree + "/" + tree.getClass + " at: " + tree.pos)
} }
// emit conversion // emit conversion

View File

@ -613,22 +613,12 @@ trait ParallelMatching extends ast.TreeDSL
val subsumed = yeses map (x => (x.bx, x.subsumed)) val subsumed = yeses map (x => (x.bx, x.subsumed))
val remaining = noes map (x => (x.bx, x.remaining)) 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 = private def mkZipped =
for (Yes(j, moreSpecific, subsumed) <- yeses) yield for (Yes(j, moreSpecific, subsumed) <- yeses) yield
j -> (moreSpecific :: subsumed) j -> (moreSpecific :: subsumed)
lazy val casted = scrut castedTo pmatch.headType 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) private def isAnyMoreSpecific = yeses exists (x => !x.moreSpecific.isEmpty)
lazy val (subtests, subtestVars) = lazy val (subtests, subtestVars) =
@ -872,37 +862,44 @@ trait ParallelMatching extends ast.TreeDSL
} }
final def condition(tpe: Type, scrutTree: Tree, isBound: Boolean): Tree = { final def condition(tpe: Type, scrutTree: Tree, isBound: Boolean): Tree = {
assert((tpe ne NoType) && (scrutTree.tpe ne NoType)) 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
// 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)))
typer typed (tpe match { // See ticket #1503 for the motivation behind checking for a binding.
case ct: ConstantType => ct.value match { // The upshot is that it is unsound to assume equality means the right
case v @ Constant(null) if scrutTree.tpe.isAnyRef => scrutTree OBJ_EQ NULL // type, but if the value doesn't appear on the right hand side of the
case v => scrutTree MEMBER_== Literal(v) // match that's unimportant; so we add an instance check only if there
} // is a binding.
case _: SingletonType if useEqTest => def bindingWarning() = {
val eqTest = REF(tpe.termSymbol) MEMBER_== scrutTree 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.")
}
}
// See ticket #1503 for the motivation behind checking for a binding. def genEquals(sym: Symbol): Tree = {
// The upshot is that it is unsound to assume equality means the right val t1: Tree = REF(sym) MEMBER_== scrutTree
// 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 if (isBound) {
// is a binding. bindingWarning()
if (isBound) { t1 AND (scrutTree IS tpe.widen)
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.") else t1
} }
eqTest AND (scrutTree IS tpe.widen)
} typer typed {
else eqTest tpe match {
case ConstantType(Constant(null)) if isRef => scrutTree OBJ_EQ NULL
case _ if scrutTree.tpe <:< tpe && tpe.isAnyRef => scrutTree OBJ_!= NULL case ConstantType(Constant(value)) => scrutTree MEMBER_== Literal(value)
case _ => scrutTree IS tpe 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 */ /** adds a test comparing the dynamic outer to the static outer */