aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala3
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala48
-rw-r--r--test/dotc/scala-collections.whitelist2
3 files changed, 36 insertions, 17 deletions
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 1271d7f6a..c8a9dc13b 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -348,6 +348,9 @@ object Flags {
/** A bridge method. Set by Erasure */
final val Bridge = termFlag(34, "<bridge>")
+ /** All class attributes are fully defined */
+ final val FullyCompleted = typeFlag(34, "<fully-completed>")
+
/** Symbol is a Java varargs bridge */ // (needed?)
final val VBridge = termFlag(35, "<vbridge>") // TODO remove
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
diff --git a/test/dotc/scala-collections.whitelist b/test/dotc/scala-collections.whitelist
index 4f3eeeed5..a5fce1020 100644
--- a/test/dotc/scala-collections.whitelist
+++ b/test/dotc/scala-collections.whitelist
@@ -140,7 +140,7 @@
# breaks genMapLike https://github.com/lampepfl/dotty/issues/937
#./scala-scala/src/library/scala/collection/GenTraversable.scala
-#./scala-scala/src/library/scala/collection/GenTraversableLike.scala
+./scala-scala/src/library/scala/collection/GenTraversableLike.scala
./scala-scala/src/library/scala/collection/GenTraversableOnce.scala
./scala-scala/src/library/scala/collection/IndexedSeq.scala