summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala21
-rw-r--r--test/files/run/castsingleton.check2
-rw-r--r--test/files/run/castsingleton.scala11
3 files changed, 28 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index c5fd840973..ba7eac7ea0 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -560,7 +560,7 @@ trait ParallelMatching extends ast.TreeDSL
j -> (moreSpecific :: subsumed)
lazy val casted = scrut castedTo pmatch.headType
- lazy val cond = condition(checkErroneous(casted), scrut)
+ lazy val cond = condition(checkErroneous(casted), scrut, head.boundVariables.nonEmpty)
private def isAnyMoreSpecific = yeses exists (x => !x.moreSpecific.isEmpty)
lazy val (subtests, subtestVars) =
@@ -803,17 +803,17 @@ trait ParallelMatching extends ast.TreeDSL
/** returns the condition in "if (cond) k1 else k2"
*/
- final def condition(tpe: Type, scrut: Scrutinee): Tree = {
+ final def condition(tpe: Type, scrut: Scrutinee, isBound: Boolean): Tree = {
assert(scrut.isDefined)
- val cond = handleOuter(condition(tpe, scrut.id))
+ val cond = handleOuter(condition(tpe, scrut.id, isBound))
if (!needsOuterTest(tpe, scrut.tpe, owner)) cond
else addOuterCondition(cond, tpe, scrut.id)
}
- final def condition(tpe: Type, scrutTree: Tree): Tree = {
+ 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 useEqTest = tpe.termSymbol.isModule || (tpe.prefix eq NoPrefix)
// case SingleType(_, _) | ThisType(_) | SuperType(_, _) =>
// val cmpOp = if (targ.tpe <:< AnyValClass.tpe) Any_equals else Object_eq
@@ -824,7 +824,16 @@ trait ParallelMatching extends ast.TreeDSL
case v @ Constant(null) if scrutTree.tpe.isAnyRef => scrutTree ANY_EQ NULL
case v => scrutTree MEMBER_== Literal(v)
}
- case _: SingletonType if useEqTest => REF(tpe.termSymbol) MEMBER_== scrutTree
+ 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) eqTest AND (scrutTree IS tpe.widen)
+ else eqTest
+
case _ if scrutTree.tpe <:< tpe && tpe.isAnyRef => scrutTree OBJ_!= NULL
case _ => scrutTree IS tpe
})
diff --git a/test/files/run/castsingleton.check b/test/files/run/castsingleton.check
new file mode 100644
index 0000000000..49742281f0
--- /dev/null
+++ b/test/files/run/castsingleton.check
@@ -0,0 +1,2 @@
+L()
+L()
diff --git a/test/files/run/castsingleton.scala b/test/files/run/castsingleton.scala
new file mode 100644
index 0000000000..f907467741
--- /dev/null
+++ b/test/files/run/castsingleton.scala
@@ -0,0 +1,11 @@
+object Test extends Application {
+ case class L();
+ object N extends L();
+
+ def empty(xs : L) : Unit = xs match {
+ case x@N => println(x); println(x);
+ case x => println(x); println(x);
+ }
+
+ empty(L())
+}