Skip to content

Commit 5fce8e6

Browse files
Merge pull request #9083 from dotty-staging/fix-#9069
Fix #9069: Complete children of sealed classes early
2 parents e4bb383 + e8b25e5 commit 5fce8e6

File tree

7 files changed

+48
-21
lines changed

7 files changed

+48
-21
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ object Flags {
339339
val (_, DefaultMethod @ _, _) = newFlags(38, "<defaultmethod>")
340340

341341
/** Symbol is an enum class or enum case (if used with case) */
342-
val (Enum @ _, _, _) = newFlags(40, "enum")
342+
val (Enum @ _, EnumVal @ _, _) = newFlags(40, "enum")
343343

344344
/** An export forwarder */
345345
val (Exported @ _, _, _) = newFlags(41, "exported")
@@ -530,7 +530,7 @@ object Flags {
530530
val DeferredOrLazyOrMethod: FlagSet = Deferred | Lazy | Method
531531
val DeferredOrTermParamOrAccessor: FlagSet = Deferred | ParamAccessor | TermParam // term symbols without right-hand sides
532532
val DeferredOrTypeParam: FlagSet = Deferred | TypeParam // type symbols without right-hand sides
533-
val EnumValue: FlagSet = Enum | StableRealizable // A Scala enum value
533+
val EnumValue: FlagSet = Enum | StableRealizable // A Scala enum value
534534
val StableOrErased: FlagSet = Erased | StableRealizable // Assumed to be pure
535535
val ExtensionMethod: FlagSet = Extension | Method
536536
val FinalOrInline: FlagSet = Final | Inline

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

+33
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,39 @@ 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)(using Context) =
1587+
// Possible children are: classes extending Scala classes and
1588+
// Scala or Java enum values that are defined in owner.
1589+
// If owner is a package, we complete only
1590+
// children that are defined in the same file as their parents.
1591+
def maybeChild(sym: Symbol) =
1592+
(sym.isClass && !this.is(JavaDefined) || sym.originDenotation.is(EnumVal))
1593+
&& !owner.is(Package)
1594+
|| sym.originDenotation.infoOrCompleter.match
1595+
case _: SymbolLoaders.SecondCompleter => sym.associatedFile == this.symbol.associatedFile
1596+
case _ => false
1597+
1598+
if owner.isClass then
1599+
for c <- owner.info.decls.toList if maybeChild(c) do
1600+
c.ensureCompleted()
1601+
end completeChildrenIn
1602+
1603+
if is(Sealed) then
1604+
if !is(ChildrenQueried) then
1605+
// Make sure all visible children are completed, so that
1606+
// they show up in Child annotations. A possible child is visible if it
1607+
// is defined in the same scope as `cls` or in the companion object of `cls`.
1608+
completeChildrenIn(owner)
1609+
completeChildrenIn(companionClass)
1610+
setFlag(ChildrenQueried)
1611+
1612+
annotations.collect { case Annotation.Child(child) => child }.reverse
1613+
end children
15811614
}
15821615

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

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

+1-1
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

+1-14
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

+3
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

+4
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

tests/run-staging/i6281.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import scala.quoted._
22
import scala.quoted.staging._
33

4-
object Test extends App {
4+
sealed trait HList
5+
sealed trait HNil extends HList
6+
sealed trait ::[E, T <: HList] extends HList
57

6-
sealed trait HList
7-
sealed trait HNil extends HList
8-
sealed trait ::[E, T <: HList] extends HList
8+
object Test extends App {
99

1010
type STM[A, L <: HList] = L match {
1111
case HNil => Expr[A]

0 commit comments

Comments
 (0)