summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-02-21 15:01:27 +0100
committerJason Zaugg <jzaugg@gmail.com>2014-02-21 15:01:27 +0100
commite72f77be2e2c47e1f3905089e16c2ba4826de089 (patch)
treeaec7a9fc346c40941f5e45a28c126d0bbb3afab2
parentaf709cc0ec8ae7762eafcb5cd3aa260864e84c8c (diff)
parent971358bf0a90d7bbb6af7cc34eb282e9ade66460 (diff)
downloadscala-e72f77be2e2c47e1f3905089e16c2ba4826de089.tar.gz
scala-e72f77be2e2c47e1f3905089e16c2ba4826de089.tar.bz2
scala-e72f77be2e2c47e1f3905089e16c2ba4826de089.zip
Merge pull request #3558 from adriaanm/t4577
SI-4577 singleton type pattern test should use `eq`, not `==`
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala3
-rw-r--r--test/files/run/t4577.scala38
3 files changed, 41 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 2a3c631a66..dc4969be43 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -261,7 +261,8 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT
}
def nonNullTest(testedBinder: Symbol) = uniqueNonNullProp(binderToUniqueTree(testedBinder))
def equalsTest(pat: Tree, testedBinder: Symbol) = uniqueEqualityProp(binderToUniqueTree(testedBinder), unique(pat))
- def eqTest(pat: Tree, testedBinder: Symbol) = uniqueEqualityProp(binderToUniqueTree(testedBinder), unique(pat)) // TODO: eq, not ==
+ // rewrite eq test to type test against the singleton type `pat.tpe`; unrelated to == (uniqueEqualityProp), could be null
+ def eqTest(pat: Tree, testedBinder: Symbol) = uniqueTypeProp(binderToUniqueTree(testedBinder), uniqueTp(pat.tpe))
def tru = True
}
ttm.renderCondition(condStrategy)
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
index a80f158949..5d8a9fecef 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
@@ -447,8 +447,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
// - Scala's arrays are invariant (so we don't drop type tests unsoundly)
if (extractorArgTypeTest) mkDefault
else expectedTp match {
- // TODO: [SPEC] the spec requires `eq` instead of `==` for singleton types - this implies sym.isStable
- case SingleType(_, sym) => and(mkEqualsTest(gen.mkAttributedQualifier(expectedTp)), mkTypeTest)
+ case SingleType(_, sym) => mkEqTest(gen.mkAttributedQualifier(expectedTp)) // SI-4577, SI-4897
case ThisType(sym) if sym.isModule => and(mkEqualsTest(CODE.REF(sym)), mkTypeTest) // must use == to support e.g. List() == Nil
case ConstantType(Constant(null)) if isAnyRef => mkEqTest(expTp(CODE.NULL))
case ConstantType(const) => mkEqualsTest(expTp(Literal(const)))
diff --git a/test/files/run/t4577.scala b/test/files/run/t4577.scala
new file mode 100644
index 0000000000..b08100d3ea
--- /dev/null
+++ b/test/files/run/t4577.scala
@@ -0,0 +1,38 @@
+object Test {
+ val bippy = new Symbol("bippy")
+ val imposter = new Symbol("bippy")
+ val notBippy = new Symbol("not-bippy")
+ val syms = List(bippy, imposter, notBippy)
+
+ // the equals method should only be used for case `bippy`,
+ // for the singleton type pattern, case _: bippy.type, the spec mandates `bippy eq _` as the test
+ class Symbol(val name: String) {
+ override def equals(other: Any) = other match {
+ case x: Symbol => name == x.name
+ case _ => false
+ }
+ override def toString = name
+ }
+
+ // TODO: test bytecode equality for f and fDirect (and g and gDirect),
+ // for now the optimizer doesn't quite get from `f` to `fDirect`
+ def f(s: Symbol) = s match {
+ case _: bippy.type => true
+ case _ => false
+ }
+ def fDirect(s: Symbol) = bippy eq s
+
+ def g(s: Symbol) = s match {
+ case _: bippy.type => 1
+ case `bippy` => 2
+ case _ => 3
+ }
+ def gDirect(s: Symbol) = if (bippy eq s) 1 else if (bippy == s) 2 else 3
+
+ def main(args: Array[String]): Unit = {
+ // `syms map f` should be: true false false
+ assert(syms forall (s => f(s) == fDirect(s)))
+ // `syms map g` should be: 1 2 3
+ assert(syms forall (s => g(s) == gDirect(s)))
+ }
+} \ No newline at end of file