summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2007-08-19 10:14:47 +0000
committerBurak Emir <emir@epfl.ch>2007-08-19 10:14:47 +0000
commit53e0d8562ac88ef2450caea299c8bd6a68858f74 (patch)
treecccc0fd8f7fd7f2a17030053fda915bbcd7224bf
parentf507e25804b6f1ad2ae278c3492c232e765b2a53 (diff)
downloadscala-53e0d8562ac88ef2450caea299c8bd6a68858f74.tar.gz
scala-53e0d8562ac88ef2450caea299c8bd6a68858f74.tar.bz2
scala-53e0d8562ac88ef2450caea299c8bd6a68858f74.zip
fix #1276, encoding equals test in types means ...
fix #1276, encoding equals test in types means one has be careful when using <:<... for an "equalsclass" type, extracts the type of the value which is to be compared by equality, used in optimization
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala33
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala10
-rw-r--r--test/files/run/patmatnew.scala12
3 files changed, 39 insertions, 16 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 780848a2e9..85ae65c491 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -617,14 +617,14 @@ trait ParallelMatching {
scrutinee.tpe.typeSymbol.children.forall { sym => tpes.contains(sym) }
}
- private val patternType = column.head match {
+ private val headPatternType = column.head match {
case p @ (_:Ident | _:Select) =>
singleType(p.symbol.tpe.prefix, p.symbol) //ConstantType(p.tpe.singleton)
//case p@Apply(_,_) if !p.tpe./*?type?*/symbol.hasFlag(symtab.Flags.CASE) => ConstantType(new NamedConstant(p))
case _ => column.head.tpe
}
- private val isCaseHead = isCaseClass(patternType)
- private val dummies = if(!isCaseHead) Nil else patternType.typeSymbol.caseFieldAccessors.map { x => EmptyTree }
+ private val isCaseHead = isCaseClass(headPatternType)
+ private val dummies = if(!isCaseHead) Nil else headPatternType.typeSymbol.caseFieldAccessors.map { x => EmptyTree }
//Console.println("isCaseHead = "+isCaseHead)
//Console.println("dummies = "+dummies)
@@ -653,7 +653,7 @@ trait ParallelMatching {
(pat.symbol ne null) &&
(pat.symbol != NoSymbol) &&
pat.symbol.tpe.prefix.isStable &&
- patternType =:= singleType(pat.symbol.tpe.prefix, pat.symbol)
+ headPatternType =:= singleType(pat.symbol.tpe.prefix, pat.symbol)
} catch {
case e =>
Console.println("object pattern test throws "+e.getMessage())
@@ -672,35 +672,35 @@ trait ParallelMatching {
//Console.println("pat = "+pat+" (class "+pat.getClass+")of type "+pat.tpe)
//Console.println("current pat is wild? = "+isDefaultPattern(pat))
//Console.println("current pat.symbol = "+pat.symbol+", pat.tpe "+pat.tpe)
- //Console.println("patternType = "+patternType)
- //Console.println("(current)pat.tpe <:< patternType = "+(pat.tpe <:< patternType))
- //Console.println("patternType <:< (current)pat.tpe = "+(patternType <:< pat.tpe))
- //Console.println("(current)pat.tpe =:= patternType = "+(pat.tpe <:< patternType))
+ //Console.println("headPatternType = "+headPatternType)
+ //Console.println("(current)pat.tpe <:< headPatternType = "+(pat.tpe <:< headPatternType))
+ //Console.println("headPatternType <:< (current)pat.tpe = "+(headPatternType <:< pat.tpe))
+ //Console.println("(current)pat.tpe =:= headPatternType = "+(pat.tpe <:< headPatternType))
sr = strip2(pat) match {
// case _: Bind => // cannot happen, using strip2
// case a:Alternative => // cannot happen, alternatives should be preprocessed away
- case Literal(Constant(null)) if !(patternType =:= pat.tpe) => //special case for constant null pattern
+ case Literal(Constant(null)) if !(headPatternType =:= pat.tpe) => //special case for constant null pattern
//Console.println("[1")
(ms,ss,(j,pat)::rs);
case _ if objectPattern(pat) =>
//Console.println("[2")
(EmptyTree::ms, (j,dummies)::ss, rs); // matching an object
- case Typed(p:UnApply,_) if (pat.tpe <:< patternType) =>
+ case Typed(p:UnApply,_) if (pat.tpe /*is never <equals>*/ <:< headPatternType) =>
//Console.println("unapply arg is same or *more* specific")
(p::ms, (j, dummies)::ss, rs);
- case q @ Typed(pp,_) if (pat.tpe <:< patternType) =>
+ case q @ Typed(pp,_) if (patternType_wrtEquals(pat.tpe) <:< headPatternType) =>
//Console.println("current pattern is same or *more* specific")
- ({if(pat.tpe =:= patternType) EmptyTree else q}::ms, (j, dummies)::ss, rs);
+ ({if(pat.tpe =:= headPatternType /*never true for <equals>*/) EmptyTree else q}::ms, (j, dummies)::ss, rs);
- case qq if (pat.tpe <:< patternType) && !isDefaultPattern(pat) =>
+ case qq if (patternType_wrtEquals(pat.tpe) <:< headPatternType) && !isDefaultPattern(pat) =>
//Console.println("current pattern is same or *more* specific")
- ({if(pat.tpe =:= patternType) EmptyTree else pat}::ms, (j,subpatterns(pat))::ss, rs);
+ ({if(pat.tpe =:= headPatternType /*never true for <equals>*/) EmptyTree else pat}::ms, (j,subpatterns(pat))::ss, rs);
- case _ if (patternType <:< pat.tpe) || isDefaultPattern(pat) =>
+ case _ if (headPatternType <:< pat.tpe /*never true for <equals>*/) || isDefaultPattern(pat) =>
//Console.println("current pattern is *more general*")
(EmptyTree::ms, (j, dummies)::ss, (j,pat)::rs); // subsuming (matched *and* remaining pattern)
@@ -726,7 +726,7 @@ trait ParallelMatching {
//Console.println("*** getTransition! of "+this.toString)
// the following works for type tests... what fudge is necessary for value comparisons?
// type test
- casted = if(scrutinee.tpe =:= patternType) scrutinee else newVar(scrutinee.pos, patternType)
+ casted = if(scrutinee.tpe =:= headPatternType) scrutinee else newVar(scrutinee.pos, headPatternType)
if(scrutinee.hasFlag(symtab.Flags.CAPTURED))
casted.setFlag(symtab.Flags.CAPTURED)
// succeeding => transition to translate(subsumed) (taking into account more specific)
@@ -767,6 +767,7 @@ trait ParallelMatching {
}
if(ntriples.isEmpty) None else Some(Rep(ntemps, ntriples))
}
+ //DBG("nmatrixFail = \n\n"+nmatrixFail)
(casted, nmatrix, nmatrixFail)
} /* getTransition(implicit theOwner: Symbol): (Symbol, Rep, Option[Rep]) */
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index d3db5f0a2a..d3d567225a 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -17,6 +17,16 @@ trait PatternNodes { self: transform.ExplicitOuter =>
// --- misc methods
+ /* equality checks for named constant patterns like "Foo()" are encoded as "_:<equals>[Foo().type]"
+ * and later compiled to "if(Foo() == scrutinee) ...". This method extracts type information from
+ * such an encoded type, which is used in optimization. If the argument is not an encoded equals
+ * test, it is returned as is.
+ */
+ def patternType_wrtEquals(pattpe:Type) = pattpe match {
+ case TypeRef(_,sym,arg::Nil) if sym eq definitions.EqualsPatternClass =>
+ arg
+ case x => x
+ }
/** returns if pattern can be considered a no-op test ??for expected type?? */
final def isDefaultPattern(pattern:Tree): Boolean = pattern match {
case Bind(_, p) => isDefaultPattern(p)
diff --git a/test/files/run/patmatnew.scala b/test/files/run/patmatnew.scala
index c55e7821df..a28f94c539 100644
--- a/test/files/run/patmatnew.scala
+++ b/test/files/run/patmatnew.scala
@@ -28,6 +28,7 @@ object Test extends TestConsoleMain {
new SimpleUnapply,
new Test717,
new TestGuards,
+ TestEqualsPatternOpt,
new TestStream,
new Test903,
new Test1093,
@@ -101,6 +102,17 @@ object Test extends TestConsoleMain {
}
}
+ object TestEqualsPatternOpt extends TestCase("test EqualsPatternClass in combination with MixTypes opt, bug #1276") {
+ val NoContext = new Object
+ override def runTest {
+ assertEquals(1,((NoContext:Any) match {
+ case that : AnyRef if this eq that => 0
+ case NoContext => 1
+ case _ => 2
+ }))
+ }
+ }
+
class TestStream extends TestCase("unapply for Streams") {
def sum(stream: Stream[int]): int =
stream match {