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:
parent
2adc29ea8b
commit
dd752c9e33
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue