aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/SymDenotations.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-11-15 11:48:37 +0100
committerMartin Odersky <odersky@gmail.com>2015-11-17 17:53:39 +0100
commite5fcf57b1e62e420c611ed58d475d081d95f9048 (patch)
tree1a93cea5e3646036e62be3eb8a938d953a9eebcb /src/dotty/tools/dotc/core/SymDenotations.scala
parentc435a8a2e3df50f3ca41f2f9f9f9d8d22a037785 (diff)
downloaddotty-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.scala48
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