diff options
Diffstat (limited to 'src/reflect/scala')
4 files changed, 28 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index fd8f51cfb1..fc49de1cf6 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -81,4 +81,10 @@ trait StdAttachments { /** An attachment carrying information between uncurry and erasure */ case class TypeParamVarargsAttachment(val typeParamRef: Type) + + /** Attached to a class symbol to indicate that its children have been observed + * via knownDirectSubclasses. Children added subsequently will trigger an + * error to indicate that the earlier observation was incomplete. + */ + case object KnownDirectSubclassesCalled extends PlainAttachment } diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 0da153349a..e664b5ad08 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -121,6 +121,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => def knownDirectSubclasses = { // See `getFlag` to learn more about the `isThreadsafe` call in the body of this method. if (!isCompilerUniverse && !isThreadsafe(purpose = AllOps)) initialize + + enclosingPackage.info.decls.foreach { sym => + if(sourceFile == sym.sourceFile) { + sym.rawInfo.forceDirectSuperclasses + } + } + + if(!isPastTyper) + updateAttachment(KnownDirectSubclassesCalled) + children } @@ -3298,7 +3308,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var childSet: Set[Symbol] = Set() override def children = childSet - override def addChild(sym: Symbol) { childSet = childSet + sym } + override def addChild(sym: Symbol) { + if(!isPastTyper && hasAttachment[KnownDirectSubclassesCalled.type] && !childSet.contains(sym)) + globalError(s"knownDirectSubclasses of ${this.name} observed before subclass ${sym.name} registered") + + childSet = childSet + sym + } def anonOrRefinementString = { if (hasCompleteInfo) { diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index dc35053835..fa5a1a25ad 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -313,6 +313,11 @@ trait Types /** If this is a lazy type, assign a new type to `sym`. */ def complete(sym: Symbol) {} + /** If this is a lazy type corresponding to a subclass add it to its + * parents children + */ + def forceDirectSuperclasses: Unit = () + /** The term symbol associated with the type * Note that the symbol of the normalized type is returned (@see normalize) */ diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index dbafbfc6ba..d5d62b2203 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -48,6 +48,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.OuterArgCanBeElided this.UseInvokeSpecial this.TypeParamVarargsAttachment + this.KnownDirectSubclassesCalled this.noPrint this.typeDebug this.Range |