diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala index 03d5ac13665b..75391ae5c23f 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala @@ -615,14 +615,11 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { * The members are sorted by name and signature to guarantee a stable ordering. */ private def sortedMembersBasedOnFlags(tp: Type, required: Flag, excluded: FlagSet): List[Symbol] = { - // The output of `memberNames` is a Set, sort it to guarantee a stable ordering. - val names = tp.memberNames(takeAllFilter).toSeq.sorted - val buffer = mutable.ListBuffer[Symbol]() - names.foreach { name => - buffer ++= tp.memberBasedOnFlags(name, required, excluded) + val names = tp.memberNames(takeAllFilter).toList + names.flatMap { name => + tp.memberBasedOnFlags(name, required, excluded) .alternatives.sortBy(_.signature)(Signature.lexicographicOrdering).map(_.symbol) } - buffer.toList } /* diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 7f47f1696cd6..52c99122fafa 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -22,6 +22,7 @@ import java.util.WeakHashMap import scala.util.control.NonFatal import config.Config import reporting._ +import collection.immutable.SortedSet import collection.mutable import transform.TypeUtils._ @@ -2231,7 +2232,7 @@ object SymDenotations { } } - def memberNames(keepOnly: NameFilter)(implicit onBehalf: MemberNames, ctx: Context): Set[Name] = + def memberNames(keepOnly: NameFilter)(implicit onBehalf: MemberNames, ctx: Context): SortedSet[Name] = if (this.is(PackageClass) || !Config.cacheMemberNames) computeMemberNames(keepOnly) // don't cache package member names; they might change else { @@ -2239,8 +2240,8 @@ object SymDenotations { memberNamesCache(keepOnly, this) } - def computeMemberNames(keepOnly: NameFilter)(implicit onBehalf: MemberNames, ctx: Context): Set[Name] = { - var names = Set[Name]() + def computeMemberNames(keepOnly: NameFilter)(implicit onBehalf: MemberNames, ctx: Context): SortedSet[Name] = { + var names = SortedSet[Name]() def maybeAdd(name: Name) = if (keepOnly(thisType, name)) names += name try { for (p <- parentSyms if p.isClass) @@ -2466,8 +2467,8 @@ object SymDenotations { end computeMembersNamed /** The union of the member names of the package and the package object */ - override def memberNames(keepOnly: NameFilter)(implicit onBehalf: MemberNames, ctx: Context): Set[Name] = { - def recur(pobjs: List[ClassDenotation], acc: Set[Name]): Set[Name] = pobjs match { + override def memberNames(keepOnly: NameFilter)(implicit onBehalf: MemberNames, ctx: Context): SortedSet[Name] = { + def recur(pobjs: List[ClassDenotation], acc: SortedSet[Name]): SortedSet[Name] = pobjs match { case pcls :: pobjs1 => recur(pobjs1, acc.union(pcls.memberNames(keepOnly))) case nil => @@ -2752,7 +2753,7 @@ object SymDenotations { /** A cache for sets of member names, indexed by a NameFilter */ trait MemberNames extends InheritedCache { def apply(keepOnly: NameFilter, clsd: ClassDenotation) - (implicit onBehalf: MemberNames, ctx: Context): Set[Name] + (implicit onBehalf: MemberNames, ctx: Context): SortedSet[Name] } object MemberNames { @@ -2813,7 +2814,7 @@ object SymDenotations { } private class MemberNamesImpl(createdAt: Period) extends InheritedCacheImpl(createdAt) with MemberNames { - private var cache: SimpleIdentityMap[NameFilter, Set[Name]] = SimpleIdentityMap.empty + private var cache: SimpleIdentityMap[NameFilter, SortedSet[Name]] = SimpleIdentityMap.empty final def isValid(using Context): Boolean = cache != null && isValidAt(ctx.phase) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index b384cbdcb084..fe0f309029ed 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -29,6 +29,7 @@ import printing.Texts._ import printing.Printer import Hashable._ import Uniques._ +import collection.immutable.SortedSet import collection.mutable import config.Config import config.Feature @@ -902,7 +903,7 @@ object Types { * @note: OK to use a Set[Name] here because Name hashcodes are replayable, * hence the Set will always give the same names in the same order. */ - final def memberNames(keepOnly: NameFilter, pre: Type = this)(using Context): Set[Name] = this match { + final def memberNames(keepOnly: NameFilter, pre: Type = this)(using Context): SortedSet[Name] = this match { case tp: ClassInfo => val names = tp.cls.classDenot.memberNames(keepOnly) if keepOnly.isStable then names else names.filter(keepOnly(pre, _)) @@ -916,7 +917,7 @@ object Types { case tp: OrType => tp.tp1.memberNames(keepOnly, pre) & tp.tp2.memberNames(keepOnly, pre) case _ => - Set() + SortedSet() } def memberDenots(keepOnly: NameFilter, f: (Name, mutable.Buffer[SingleDenotation]) => Unit)(using Context): Seq[SingleDenotation] = { diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 4c20f5821ca4..f3866f0b0f41 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -51,9 +51,9 @@ object RefChecks { } { val defaultGetterNames = defaultGetterClass.asClass.memberNames(defaultMethodFilter) - val defaultMethodNames = defaultGetterNames map { _ replace { + val defaultMethodNames = defaultGetterNames.map { _ replace { case DefaultGetterName(methName, _) => methName - }} + }}(Names.NameOrdering) for (name <- defaultMethodNames) { val methods = clazz.info.member(name).alternatives.map(_.symbol)