diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 0b2aa4133983..0b8eb22034b0 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -339,7 +339,7 @@ object Flags { val (_, DefaultMethod @ _, _) = newFlags(38, "") /** Symbol is an enum class or enum case (if used with case) */ - val (Enum @ _, _, _) = newFlags(40, "enum") + val (Enum @ _, EnumVal @ _, _) = newFlags(40, "enum") /** An export forwarder */ val (Exported @ _, _, _) = newFlags(41, "exported") @@ -530,7 +530,7 @@ object Flags { val DeferredOrLazyOrMethod: FlagSet = Deferred | Lazy | Method val DeferredOrTermParamOrAccessor: FlagSet = Deferred | ParamAccessor | TermParam // term symbols without right-hand sides val DeferredOrTypeParam: FlagSet = Deferred | TypeParam // type symbols without right-hand sides - val EnumValue: FlagSet = Enum | StableRealizable // A Scala enum value + val EnumValue: FlagSet = Enum | StableRealizable // A Scala enum value val StableOrErased: FlagSet = Erased | StableRealizable // Assumed to be pure val ExtensionMethod: FlagSet = Extension | Method val FinalOrInline: FlagSet = Final | Inline diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index b3f952e292a2..01a0437c9ad3 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1578,6 +1578,39 @@ object SymDenotations { if (is(Private)) copySymDenotation(name = expandedName, initFlags = this.flags &~ Private) else this + + /** If this is a sealed class, its known children in the order of textual occurrence + */ + def children(using Context): List[Symbol] = + + def completeChildrenIn(owner: Symbol)(using Context) = + // Possible children are: classes extending Scala classes and + // Scala or Java enum values that are defined in owner. + // If owner is a package, we complete only + // children that are defined in the same file as their parents. + def maybeChild(sym: Symbol) = + (sym.isClass && !this.is(JavaDefined) || sym.originDenotation.is(EnumVal)) + && !owner.is(Package) + || sym.originDenotation.infoOrCompleter.match + case _: SymbolLoaders.SecondCompleter => sym.associatedFile == this.symbol.associatedFile + case _ => false + + if owner.isClass then + for c <- owner.info.decls.toList if maybeChild(c) do + c.ensureCompleted() + end completeChildrenIn + + if is(Sealed) then + if !is(ChildrenQueried) then + // Make sure all visible children are completed, so that + // they show up in Child annotations. A possible child is visible if it + // is defined in the same scope as `cls` or in the companion object of `cls`. + completeChildrenIn(owner) + completeChildrenIn(companionClass) + setFlag(ChildrenQueried) + + annotations.collect { case Annotation.Child(child) => child }.reverse + end children } /** The contents of a class definition during a period diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index 44213d2c3cdc..c1d6b5500bf9 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1780,7 +1780,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend } def Symbol_children(self: Symbol)(using ctx: Context): List[Symbol] = - dotty.tools.dotc.transform.SymUtils(self).children + self.children private def isField(sym: Symbol)(using ctx: Context): Boolean = sym.isTerm && !sym.is(Flags.Method) diff --git a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala index ff7890f62a4c..cfeb1d68af8b 100644 --- a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala @@ -188,21 +188,8 @@ class SymUtils(val self: Symbol) extends AnyVal { || sym.isType && isAccessible(sym.owner, cls) !isAccessible(self.owner, cls) - /** If this is a sealed class, its known children in the order of textual occurrence */ - def children(implicit ctx: Context): List[Symbol] = { - if (self.isType) - self.setFlag(ChildrenQueried) - - if (self.isAllOf(JavaEnumTrait)) - self.linkedClass.info.decls.foreach(_.ensureCompleted()) - - self.annotations.collect { - case Annotation.Child(child) => child - }.reverse - } - def hasAnonymousChild(implicit ctx: Context): Boolean = - children.exists(_ `eq` self) + self.children.exists(_ `eq` self) /** Is symbol directly or indirectly owned by a term symbol? */ @tailrec final def isLocal(implicit ctx: Context): Boolean = { diff --git a/tests/pos/i9069/Test.scala b/tests/pos/i9069/Test.scala new file mode 100644 index 000000000000..99815c06c6cd --- /dev/null +++ b/tests/pos/i9069/Test.scala @@ -0,0 +1,3 @@ +def Test = + val mirror = summon[deriving.Mirror.SumOf[Foo]] + summon[mirror.MirroredElemTypes =:= (Foo.Baz.type, Bar)] diff --git a/tests/pos/i9069/Wrapper.scala b/tests/pos/i9069/Wrapper.scala new file mode 100644 index 000000000000..1c3952b683e1 --- /dev/null +++ b/tests/pos/i9069/Wrapper.scala @@ -0,0 +1,4 @@ +sealed trait Foo +object Foo: + case object Baz extends Foo +case class Bar(x: Int) extends Foo diff --git a/tests/run-staging/i6281.scala b/tests/run-staging/i6281.scala index 26c0bc4c0318..e390a09aa9e7 100644 --- a/tests/run-staging/i6281.scala +++ b/tests/run-staging/i6281.scala @@ -1,11 +1,11 @@ import scala.quoted._ import scala.quoted.staging._ -object Test extends App { +sealed trait HList +sealed trait HNil extends HList +sealed trait ::[E, T <: HList] extends HList - sealed trait HList - sealed trait HNil extends HList - sealed trait ::[E, T <: HList] extends HList +object Test extends App { type STM[A, L <: HList] = L match { case HNil => Expr[A]