Skip to content

Replace Set with UniqList in memberNames #13973

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

/*
Expand Down
19 changes: 10 additions & 9 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Variances.Variance
import annotation.tailrec
import util.SimpleIdentityMap
import util.Stats
import util.UniqList
import java.util.WeakHashMap
import scala.util.control.NonFatal
import config.Config
Expand Down Expand Up @@ -2231,16 +2232,16 @@ object SymDenotations {
}
}

def memberNames(keepOnly: NameFilter)(implicit onBehalf: MemberNames, ctx: Context): Set[Name] =
def memberNames(keepOnly: NameFilter)(implicit onBehalf: MemberNames, ctx: Context): UniqList[Name] =
if (this.is(PackageClass) || !Config.cacheMemberNames)
computeMemberNames(keepOnly) // don't cache package member names; they might change
else {
if (!memberNamesCache.isValid) memberNamesCache = MemberNames.newCache()
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): UniqList[Name] = {
val names = new UniqList.Builder[Name]
def maybeAdd(name: Name) = if (keepOnly(thisType, name)) names += name
try {
for (p <- parentSyms if p.isClass)
Expand All @@ -2253,7 +2254,7 @@ object SymDenotations {
else info.decls.iterator.filter(_.isOneOf(GivenOrImplicitVal))
else info.decls.iterator
for (sym <- ownSyms) maybeAdd(sym.name)
names
names.result
}
catch {
case ex: Throwable =>
Expand Down Expand Up @@ -2466,10 +2467,10 @@ 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): UniqList[Name] = {
def recur(pobjs: List[ClassDenotation], acc: UniqList[Name]): UniqList[Name] = pobjs match {
case pcls :: pobjs1 =>
recur(pobjs1, acc.union(pcls.memberNames(keepOnly)))
recur(pobjs1, acc | pcls.memberNames(keepOnly))
case nil =>
acc
}
Expand Down Expand Up @@ -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): UniqList[Name]
}

object MemberNames {
Expand Down Expand Up @@ -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, UniqList[Name]] = SimpleIdentityMap.empty

final def isValid(using Context): Boolean =
cache != null && isValidAt(ctx.phase)
Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Variances.{Variance, varianceFromInt, varianceToInt, setStructuralVarianc
import typer.Nullables
import util.Stats._
import util.SimpleIdentitySet
import util.UniqList
import ast.tpd._
import ast.TreeTypeMap
import printing.Texts._
Expand Down Expand Up @@ -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): UniqList[Name] = this match {
case tp: ClassInfo =>
val names = tp.cls.classDenot.memberNames(keepOnly)
if keepOnly.isStable then names else names.filter(keepOnly(pre, _))
Expand All @@ -916,7 +917,7 @@ object Types {
case tp: OrType =>
tp.tp1.memberNames(keepOnly, pre) & tp.tp2.memberNames(keepOnly, pre)
case _ =>
Set()
UniqList.empty
}

def memberDenots(keepOnly: NameFilter, f: (Name, mutable.Buffer[SingleDenotation]) => Unit)(using Context): Seq[SingleDenotation] = {
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ object RefChecks {
}
{
val defaultGetterNames = defaultGetterClass.asClass.memberNames(defaultMethodFilter)
val defaultMethodNames = defaultGetterNames map { _ replace {
val defaultMethodNames = defaultGetterNames.toList.map { _ replace {
case DefaultGetterName(methName, _) => methName
}}
}}.distinct

for (name <- defaultMethodNames) {
val methods = clazz.info.member(name).alternatives.map(_.symbol)
Expand Down
21 changes: 21 additions & 0 deletions compiler/src/dotty/tools/dotc/util/UniqList.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dotty.tools.dotc.util

opaque type UniqList[+A] >: Null <: AnyRef = List[A]

object UniqList:
def empty: UniqList[Nothing] = Nil
extension [A](xs: UniqList[A])
def foreach(f: A => Unit): Unit = xs.foreach(f)
def filter(p: A => Boolean): UniqList[A] = xs.filter(p)
def + (x: A): UniqList[A] = if xs.contains(x) then xs else xs :+ x
def & (ys: UniqList[A]): UniqList[A] = xs.filter(ys.contains)
def | (ys: UniqList[A]): UniqList[A] = (xs ::: ys).distinct
def toList: List[A] = xs

class Builder[A] extends scala.collection.mutable.Builder[A, UniqList[A]]:
private val xs = new scala.collection.mutable.ListBuffer[A]
override def addOne(x: A): this.type = { xs += x; this }
override def addAll(ys: IterableOnce[A]): this.type = { xs ++= ys; this }
override def clear(): Unit = xs.clear()
override def result(): UniqList[A] = xs.distinct.toList
override def sizeHint(size: Int) = xs.sizeHint(size)