diff options
author | Martin Odersky <odersky@gmail.com> | 2015-11-15 11:48:37 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-11-17 17:53:39 +0100 |
commit | e5fcf57b1e62e420c611ed58d475d081d95f9048 (patch) | |
tree | 1a93cea5e3646036e62be3eb8a938d953a9eebcb /src/dotty/tools/dotc/core/SymDenotations.scala | |
parent | c435a8a2e3df50f3ca41f2f9f9f9d8d22a037785 (diff) | |
download | dotty-e5fcf57b1e62e420c611ed58d475d081d95f9048.tar.gz dotty-e5fcf57b1e62e420c611ed58d475d081d95f9048.tar.bz2 dotty-e5fcf57b1e62e420c611ed58d475d081d95f9048.zip |
Fix problems arising when hierarchies of classes are under completion
Fix problems arising when hierarchies of classes are under completion at the same time.
In this case it can happen that we see a subclass (e.g. Arrays.scala) which depends
on a superclass (e.g. GenTraversableLike.scala) that itself does not have its parents
defined yet. Previously, several things went wrong here
- One of the base classes would be marked as frozen, even though it dod not have all
members entered yet. This led to an error in finger printing.
- The baseclasses and super class bits of the subclass would be computed before the parents
of the middle class were known. The baseclasses would then be chached, leading to
false results for isDerivedFrom.
We need to refine the logic for computing base classes, super class bits, and fingerprints
to account for that issue.
Diffstat (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 2f2703397..00ca99da5 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1213,8 +1213,17 @@ object SymDenotations { * ClassDenotations compiled from source are first completed, then fully completed. * @see Namer#ClassCompleter */ - private def isFullyCompleted(implicit ctx: Context): Boolean = - isCompleted && classParents.nonEmpty + private def isFullyCompleted(implicit ctx: Context): Boolean = { + def isFullyCompletedRef(tp: TypeRef) = tp.denot match { + case d: ClassDenotation => d.isFullyCompleted + case _ => false + } + def isLocallyFullyCompleted = + if (classParents.isEmpty) is(Package) || symbol.eq(defn.AnyClass) + else classParents.forall(isFullyCompletedRef) + flagsUNSAFE.is(FullyCompleted) || + isCompleted && isLocallyFullyCompleted && { setFlag(FullyCompleted); true } + } // ------ syncing inheritance-related info ----------------------------- @@ -1300,7 +1309,7 @@ object SymDenotations { baseTypeRefValid = ctx.runId } - private def computeBases(implicit ctx: Context): Unit = { + private def computeBases(implicit ctx: Context): (List[ClassSymbol], BitSet) = { if (myBaseClasses eq Nil) throw CyclicReference(this) myBaseClasses = Nil val seen = new mutable.BitSet @@ -1324,8 +1333,14 @@ object SymDenotations { case nil => to } - myBaseClasses = classSymbol :: addParentBaseClasses(classParents, Nil) - mySuperClassBits = seen.toImmutable + val bcs = classSymbol :: addParentBaseClasses(classParents, Nil) + val scbits = seen.toImmutable + if (isFullyCompleted) { + myBaseClasses = bcs + mySuperClassBits = scbits + } + else myBaseClasses = null + (bcs, scbits) } /** A bitset that contains the superId's of all base classes */ @@ -1333,8 +1348,7 @@ object SymDenotations { if (classParents.isEmpty) BitSet() // can happen when called too early in Namers else { checkBasesUpToDate() - if (mySuperClassBits == null) computeBases - mySuperClassBits + if (mySuperClassBits != null) mySuperClassBits else computeBases._2 } /** The base classes of this class in linearization order, @@ -1344,8 +1358,7 @@ object SymDenotations { if (classParents.isEmpty) classSymbol :: Nil // can happen when called too early in Namers else { checkBasesUpToDate() - if (myBaseClasses == null) computeBases - myBaseClasses + if (myBaseClasses != null) myBaseClasses else computeBases._1 } final override def derivesFrom(base: Symbol)(implicit ctx: Context): Boolean = @@ -1378,9 +1391,9 @@ object SymDenotations { while (ps.nonEmpty) { val parent = ps.head.typeSymbol parent.denot match { - case classd: ClassDenotation => - fp.include(classd.memberFingerPrint) - parent.denot.setFlag(Frozen) + case parentDenot: ClassDenotation => + fp.include(parentDenot.memberFingerPrint) + if (parentDenot.isFullyCompleted) parentDenot.setFlag(Frozen) case _ => } ps = ps.tail @@ -1393,10 +1406,13 @@ object SymDenotations { * not be used for package classes because cache never * gets invalidated. */ - def memberFingerPrint(implicit ctx: Context): FingerPrint = { - if (myMemberFingerPrint == FingerPrint.unknown) myMemberFingerPrint = computeMemberFingerPrint - myMemberFingerPrint - } + def memberFingerPrint(implicit ctx: Context): FingerPrint = + if (myMemberFingerPrint != FingerPrint.unknown) myMemberFingerPrint + else { + val fp = computeMemberFingerPrint + if (isFullyCompleted) myMemberFingerPrint = fp + fp + } private[this] var myMemberCache: LRUCache[Name, PreDenotation] = null private[this] var myMemberCachePeriod: Period = Nowhere |