aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/SymDenotations.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-09-23 15:42:55 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-10-11 08:24:36 +0200
commit5289a3719c0767c1874ff1e34b825ccf3b314257 (patch)
treeef36b0fa142d70af41fd6daa77621e3020374dad /src/dotty/tools/dotc/core/SymDenotations.scala
parenta64e0a2fc8883e5a6358a04d706eb72e896f67c6 (diff)
downloaddotty-5289a3719c0767c1874ff1e34b825ccf3b314257.tar.gz
dotty-5289a3719c0767c1874ff1e34b825ccf3b314257.tar.bz2
dotty-5289a3719c0767c1874ff1e34b825ccf3b314257.zip
Fix caching logic in baseTypeRef
Typevars can be parts of larger types or underlying types of other types, which renders these other types uncacheable. The new logic takes account of that.
Diffstat (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala')
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala30
1 files changed, 16 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 556112114..711a76ad5 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -1317,6 +1317,18 @@ object SymDenotations {
case _ => bt
}
+ def inCache(tp: Type) = baseTypeRefCache.containsKey(tp)
+
+ /** Can't cache types containing type variables which are uninstantiated
+ * or whose instances can change, depending on typerstate.
+ */
+ def isCachable(tp: Type): Boolean = tp match {
+ case tp: TypeProxy => inCache(tp.underlying)
+ case tp: AndOrType => inCache(tp.tp1) && inCache(tp.tp2)
+ case tp: TypeVar => tp.inst.exists && inCache(tp.inst)
+ case _ => true
+ }
+
def computeBaseTypeRefOf(tp: Type): Type = {
Stats.record("computeBaseTypeOf")
if (symbol.isStatic && tp.derivesFrom(symbol))
@@ -1333,9 +1345,6 @@ object SymDenotations {
case _ =>
baseTypeRefOf(tp.underlying)
}
- case tp: TypeVar =>
- if (tp.inst.exists) computeBaseTypeRefOf(tp.inst)
- else Uncachable(computeBaseTypeRefOf(tp.underlying))
case tp: TypeProxy =>
baseTypeRefOf(tp.underlying)
case AndType(tp1, tp2) =>
@@ -1356,15 +1365,9 @@ object SymDenotations {
var basetp = baseTypeRefCache get tp
if (basetp == null) {
baseTypeRefCache.put(tp, NoPrefix)
- val computedBT = computeBaseTypeRefOf(tp)
- basetp = computedBT match {
- case Uncachable(basetp) =>
- baseTypeRefCache.remove(tp)
- computedBT
- case basetp =>
- baseTypeRefCache.put(tp, basetp)
- basetp
- }
+ basetp = computeBaseTypeRefOf(tp)
+ if (isCachable(tp)) baseTypeRefCache.put(tp, basetp)
+ else baseTypeRefCache.remove(tp)
} else if (basetp == NoPrefix) {
throw CyclicReference(this)
}
@@ -1444,8 +1447,7 @@ object SymDenotations {
copySymDenotation(info = ClassInfo(pre, classSymbol, ps, decls.cloneScope, selfInfo))
.installAfter(phase)
}
- }
- private case class Uncachable(tp: Type) extends UncachedGroundType
+ }
/** The denotation of a package class.
* It overrides ClassDenotation to take account of package objects when looking for members