summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-03-14 17:26:47 +0000
committerMartin Odersky <odersky@gmail.com>2007-03-14 17:26:47 +0000
commit611228e4e8a546caa5b161295070755b6d535995 (patch)
tree6fba7460adcf995ca427e421bb02fd524e465037
parente8540b5d784102174da77ea485253288b30dac90 (diff)
downloadscala-611228e4e8a546caa5b161295070755b6d535995.tar.gz
scala-611228e4e8a546caa5b161295070755b6d535995.tar.bz2
scala-611228e4e8a546caa5b161295070755b6d535995.zip
fixed bug 1001
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 3f82afde11..d368ff37f5 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -7,7 +7,7 @@
package scala.tools.nsc.symtab
import compat.Platform.currentTime
-import scala.collection.mutable.ListBuffer
+import scala.collection.mutable.{ListBuffer, HashMap}
import scala.tools.nsc.util.{HashSet, Position}
import Flags._
@@ -55,6 +55,13 @@ trait Types requires SymbolTable {
val emptyTypeArray = new Array[Type](0)
+ /** A map from lists to compound types that have the given list as parents.
+ * This is used to avoid duplication in the computation of closure and baseClasses.
+ * It makes use of the fact that these two operations depend only on the parents,
+ * not on the refinement.
+ */
+ var intersectionWitness = new HashMap[List[Type], Type]
+
/** The base class for all types */
abstract class Type {
@@ -763,7 +770,7 @@ trait Types requires SymbolTable {
closurePeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
closureCache = null
- closureCache = computeClosure
+ closureCache = memo[Array[Type], Type](computeClosure, modifyClosure(symbol.tpe))
closureDepthCache = maxDepth(closureCache)
}
//Console.println("closure(" + symbol + ") = " + List.fromArray(closureCache));//DEBUG
@@ -807,7 +814,7 @@ trait Types requires SymbolTable {
baseClassesPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
baseClassesCache = null
- baseClassesCache = computeBaseClasses
+ baseClassesCache = memo[List[Symbol], Symbol](computeBaseClasses, x => symbol :: x.baseClasses.tail)
}
}
if (baseClassesCache eq null)
@@ -815,6 +822,14 @@ trait Types requires SymbolTable {
baseClassesCache
}
+ def memo[A <: Seq[B], B](op1: => A, op2: Type => A) = intersectionWitness get parents match {
+ case Some(w) =>
+ if (w eq this) op1 else op2(w)
+ case None =>
+ intersectionWitness(parents) = this
+ op1
+ }
+
override def baseType(sym: Symbol): Type = {
val index = closurePos(sym)
if (index >= 0) closure(index) else NoType
@@ -2342,6 +2357,14 @@ trait Types requires SymbolTable {
cl1
}
+ private def modifyClosure(tp: Type)(other: Type): Array[Type] = {
+ val cl = other.closure
+ val cl1 = new Array[Type](cl.length)
+ cl1(0) = tp
+ Array.copy(cl, 1, cl1, 1, cl.length-1)
+ cl1
+ }
+
/** like map2, but returns list `xs' itself - instead of a copy - if function
* <code>f</code> maps all elements to themselves.
*/