Skip to content

Commit 46ca9a1

Browse files
committed
Handle anonymous classes with Child(self)
If a sealed class A has local or anonymous classes, add the annotation `Child(A)` to `A`. With this simple change, the exhaustivity check works without any modification.
1 parent 67d9aa6 commit 46ca9a1

File tree

3 files changed

+11
-9
lines changed

3 files changed

+11
-9
lines changed

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -842,10 +842,7 @@ class TreeUnpickler(reader: TastyReader,
842842
if (!sym.isType) { // Only terms might have leaky aliases, see the documentation of `checkNoPrivateLeaks`
843843
sym.info = ta.avoidPrivateLeaks(sym, tree.pos)
844844
}
845-
if ((sym.isClass || sym.is(CaseVal)) && sym.isLocal)
846-
// Child annotations for local classes and enum values are not pickled, so
847-
// need to be re-established here.
848-
sym.registerIfChild(late = true)
845+
849846
sym.defTree = tree
850847

851848
if (ctx.mode.is(Mode.ReadComments)) {

compiler/src/dotty/tools/dotc/transform/SymUtils.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,15 @@ class SymUtils(val self: Symbol) extends AnyVal {
133133

134134
/** If this symbol is an enum value or a named class, register it as a child
135135
* in all direct parent classes which are sealed.
136-
* @param @late If true, register only inaccessible children (all others are already
137-
* entered at this point).
138136
*/
139-
def registerIfChild(late: Boolean = false)(implicit ctx: Context): Unit = {
137+
def registerIfChild()(implicit ctx: Context): Unit = {
140138
def register(child: Symbol, parent: Type) = {
141139
val cls = parent.classSymbol
142-
if (cls.is(Sealed) && (!late || child.isInaccessibleChildOf(cls)))
143-
cls.addAnnotation(Annotation.Child(child))
140+
if (cls.is(Sealed)) {
141+
if ((child.isLocal || child.isAnonymousClass) && !self.hasAnonymousChild)
142+
cls.addAnnotation(Annotation.Child(cls))
143+
else cls.addAnnotation(Annotation.Child(child))
144+
}
144145
}
145146
if (self.isClass && !self.isEnumAnonymClass)
146147
self.asClass.classParents.foreach { parent =>
@@ -168,6 +169,9 @@ class SymUtils(val self: Symbol) extends AnyVal {
168169
case Annotation.Child(child) => child
169170
}
170171

172+
def hasAnonymousChild(implicit ctx: Context): Boolean =
173+
children.exists(_ `eq` self)
174+
171175
/** Is symbol directly or indirectly owned by a term symbol? */
172176
@tailrec final def isLocal(implicit ctx: Context): Boolean = {
173177
val owner = self.owner

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
730730
val res =
731731
(tp.classSymbol.is(Sealed) &&
732732
tp.classSymbol.is(AbstractOrTrait) &&
733+
!tp.classSymbol.hasAnonymousChild &&
733734
tp.classSymbol.children.nonEmpty ) ||
734735
dealiasedTp.isInstanceOf[OrType] ||
735736
(dealiasedTp.isInstanceOf[AndType] && {

0 commit comments

Comments
 (0)