Skip to content

Commit e32ee70

Browse files
committed
Fix #9069: Complete children of sealed classes before querying
Complete all possible children of sealed classes or traits before first querying with `children`. This way we make they register themselves with Child annotations in the parent class.
1 parent b852e14 commit e32ee70

File tree

5 files changed

+35
-15
lines changed

5 files changed

+35
-15
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,32 @@ object SymDenotations {
15781578
if (is(Private))
15791579
copySymDenotation(name = expandedName, initFlags = this.flags &~ Private)
15801580
else this
1581+
1582+
/** If this is a sealed class, its known children in the order of textual occurrence
1583+
*/
1584+
def children(using Context): List[Symbol] =
1585+
1586+
def completeChildrenIn(owner: Symbol) =
1587+
def maybeChild(c: Symbol) =
1588+
!owner.is(Package)
1589+
|| c.infoOrCompleter.match
1590+
case _: SymbolLoaders.SecondCompleter => c.associatedFile == symbol.associatedFile
1591+
case _ => false
1592+
if owner.isClass then
1593+
for c <- owner.info.decls.toList if c.isClass && maybeChild(c) do
1594+
c.ensureCompleted()
1595+
1596+
if is(Sealed) then
1597+
if !is(ChildrenQueried) && !ctx.isAfterTyper then
1598+
// During typer, make sure all visible children are completed, so that
1599+
// they show up in Child annotations. A class is visible if it is defined
1600+
// in the same scope as `cls` or in the companion object of `cls`.
1601+
completeChildrenIn(owner)
1602+
completeChildrenIn(companionClass)
1603+
setFlag(ChildrenQueried)
1604+
1605+
annotations.collect { case Annotation.Child(child) => child }.reverse
1606+
end children
15811607
}
15821608

15831609
/** The contents of a class definition during a period

compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1780,7 +1780,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
17801780
}
17811781

17821782
def Symbol_children(self: Symbol)(using ctx: Context): List[Symbol] =
1783-
dotty.tools.dotc.transform.SymUtils(self).children
1783+
self.children
17841784

17851785
private def isField(sym: Symbol)(using ctx: Context): Boolean = sym.isTerm && !sym.is(Flags.Method)
17861786

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -188,21 +188,8 @@ class SymUtils(val self: Symbol) extends AnyVal {
188188
|| sym.isType && isAccessible(sym.owner, cls)
189189
!isAccessible(self.owner, cls)
190190

191-
/** If this is a sealed class, its known children in the order of textual occurrence */
192-
def children(implicit ctx: Context): List[Symbol] = {
193-
if (self.isType)
194-
self.setFlag(ChildrenQueried)
195-
196-
if (self.isAllOf(JavaEnumTrait))
197-
self.linkedClass.info.decls.foreach(_.ensureCompleted())
198-
199-
self.annotations.collect {
200-
case Annotation.Child(child) => child
201-
}.reverse
202-
}
203-
204191
def hasAnonymousChild(implicit ctx: Context): Boolean =
205-
children.exists(_ `eq` self)
192+
self.children.exists(_ `eq` self)
206193

207194
/** Is symbol directly or indirectly owned by a term symbol? */
208195
@tailrec final def isLocal(implicit ctx: Context): Boolean = {

tests/pos/i9069/Test.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def Test =
2+
val mirror = summon[deriving.Mirror.SumOf[Foo]]
3+
summon[mirror.MirroredElemTypes =:= (Foo.Baz.type, Bar)]

tests/pos/i9069/Wrapper.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
sealed trait Foo
2+
object Foo:
3+
case object Baz extends Foo
4+
case class Bar(x: Int) extends Foo

0 commit comments

Comments
 (0)