diff options
Diffstat (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 86 |
1 files changed, 57 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index d9fa15a5f..1bb912059 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -30,8 +30,8 @@ trait SymDenotations { this: Context => initPrivateWithin: Symbol = NoSymbol)(implicit ctx: Context): SymDenotation = { val result = if (symbol.isClass) - if (initFlags is Package) new PackageClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) - else new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) + if (initFlags is Package) new PackageClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin, ctx.runId) + else new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin, ctx.runId) else new SymDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) result.validFor = stablePeriod result @@ -39,8 +39,19 @@ trait SymDenotations { this: Context => def stillValid(denot: SymDenotation): Boolean = if (denot is ValidForever) true - else if (denot.owner is PackageClass) denot.owner.decls.lookup(denot.name) eq denot.symbol - else stillValid(denot.owner) + else try { + val owner = denot.owner.denot + def isSelfSym = owner.infoOrCompleter match { + case ClassInfo(_, _, _, _, selfInfo) => selfInfo == denot.symbol + case _ => false + } + stillValid(owner) && owner.isClass && ( + (owner.decls.lookupAll(denot.name) contains denot.symbol) + || isSelfSym + ) + } catch { + case ex: StaleSymbol => false + } } object SymDenotations { @@ -732,7 +743,8 @@ object SymDenotations { name: Name, initFlags: FlagSet, initInfo: Type, - initPrivateWithin: Symbol = NoSymbol) + initPrivateWithin: Symbol, + initRunId: RunId) extends SymDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) { import util.LRUCache @@ -758,8 +770,9 @@ object SymDenotations { myTypeParams } - private def myClassParents(implicit ctx: Context): List[TypeRef] = info match { - case classInfo: ClassInfo => classInfo.myClassParents + /** The denotations of all parents in this class. */ + def classParents(implicit ctx: Context): List[TypeRef] = info match { + case classInfo: ClassInfo => classInfo.classParents case _ => Nil } @@ -768,32 +781,46 @@ object SymDenotations { * @see Namer#ClassCompleter */ private def isFullyCompleted(implicit ctx: Context): Boolean = - isCompleted && myClassParents.nonEmpty + isCompleted && classParents.nonEmpty - /** A key to verify that all caches influenced by parent classes are valid */ - private var parentDenots: List[Denotation] = null + // ------ syncing inheritance-related info ----------------------------- - /** The denotations of all parents in this class. - * Note: Always use this method instead of `classInfo.myClassParents` - * because the latter does not ensure that the `parentDenots` key - * is up-to-date, which might lead to invalid caches later on. - */ - def classParents(implicit ctx: Context): List[TypeRef] = { - val ps = myClassParents - if (parentDenots == null && ps.nonEmpty) parentDenots = ps map (_.denot) - ps - } - - /** Are caches influenced by parent classes still valid? */ - private def parentsAreValid(implicit ctx: Context): Boolean = - parentDenots == null || - parentDenots.corresponds(myClassParents)(_ eq _.denot) + private var firstRunId: RunId = initRunId /** If caches influenced by parent classes are still valid, the denotation * itself, otherwise a freshly initialized copy. */ - override def copyIfParentInvalid(implicit ctx: Context): SingleDenotation = - if (!parentsAreValid) copySymDenotation() else this + override def syncWithParents(implicit ctx: Context): SingleDenotation = { + def isYounger(tref: TypeRef) = tref.symbol.denot match { + case denot: ClassDenotation => + if (denot.validFor.runId < ctx.runId) denot.current // syncs with its parents in turn + val result = denot.firstRunId > this.firstRunId + if (result) incremental.println(s"$denot is younger than $this") + result + case _ => false + } + val parentIsYounger = (firstRunId < ctx.runId) && { + infoOrCompleter match { + case cinfo: ClassInfo => cinfo.classParents exists isYounger + case _ => false + } + } + if (parentIsYounger) { + incremental.println(s"parents of $this are invalid; symbol id = ${symbol.id}, copying ...\n") + invalidateInheritedInfo() + firstRunId = ctx.runId + } + this + } + + /** Invalidate all caches and fields that depend on base classes and their contents */ + private def invalidateInheritedInfo(): Unit = { + myBaseClasses = null + mySuperClassBits = null + myMemberFingerPrint = FingerPrint.unknown + myMemberCache = null + memberNamesCache = SimpleMap.Empty + } // ------ class-specific operations ----------------------------------- @@ -1142,8 +1169,9 @@ object SymDenotations { name: Name, initFlags: FlagSet, initInfo: Type, - initPrivateWithin: Symbol = NoSymbol) - extends ClassDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) { + initPrivateWithin: Symbol, + initRunId: RunId) + extends ClassDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin, initRunId) { private[this] var packageObjCache: SymDenotation = _ private[this] var packageObjRunId: RunId = NoRunId |