diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index b9a2f484156c..3d1cdaf759cf 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -404,7 +404,7 @@ object TypeOps: def apply(tp: Type): Type = tp match { case tp: TermRef - if toAvoid(tp.symbol) || partsToAvoid(mutable.Set.empty, tp.info).nonEmpty => + if toAvoid(tp.symbol) || partsToAvoid(Nil, tp.info).nonEmpty => tp.info.widenExpr.dealias match { case info: SingletonType => apply(info) case info => range(defn.NothingType, apply(info)) @@ -422,7 +422,7 @@ object TypeOps: } case tp: ThisType if toAvoid(tp.cls) => range(defn.NothingType, apply(classBound(tp.cls.classInfo))) - case tp: SkolemType if partsToAvoid(mutable.Set.empty, tp.info).nonEmpty => + case tp: SkolemType if partsToAvoid(Nil, tp.info).nonEmpty => range(defn.NothingType, apply(tp.info)) case tp: TypeVar if mapCtx.typerState.constraint.contains(tp) => val lo = TypeComparer.instanceType( diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 53c6638387d6..6a3259524a7c 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -392,20 +392,13 @@ object Types { final def foreachPart(p: Type => Unit, stopAtStatic: Boolean = false)(using Context): Unit = new ForeachAccumulator(p, stopAtStatic).apply((), this) - /** The parts of this type which are type or term refs */ - final def namedParts(using Context): collection.Set[NamedType] = - namedPartsWith(alwaysTrue) - /** The parts of this type which are type or term refs and which * satisfy predicate `p`. * * @param p The predicate to satisfy - * @param excludeLowerBounds If set to true, the lower bounds of abstract - * types will be ignored. */ - def namedPartsWith(p: NamedType => Boolean, excludeLowerBounds: Boolean = false) - (using Context): collection.Set[NamedType] = - new NamedPartsAccumulator(p, excludeLowerBounds).apply(mutable.LinkedHashSet(), this) + def namedPartsWith(p: NamedType => Boolean)(using Context): List[NamedType] = + new NamedPartsAccumulator(p).apply(Nil, this) /** Map function `f` over elements of an AndType, rebuilding with function `g` */ def mapReduceAnd[T](f: Type => T)(g: (T, T) => T)(using Context): T = stripTypeVar match { @@ -5520,38 +5513,34 @@ object Types { override def hash(x: Type): Int = System.identityHashCode(x) override def isEqual(x: Type, y: Type) = x.eq(y) - class NamedPartsAccumulator(p: NamedType => Boolean, excludeLowerBounds: Boolean = false) - (using Context) extends TypeAccumulator[mutable.Set[NamedType]] { - override def stopAtStatic: Boolean = false - def maybeAdd(x: mutable.Set[NamedType], tp: NamedType): mutable.Set[NamedType] = if (p(tp)) x += tp else x + class NamedPartsAccumulator(p: NamedType => Boolean)(using Context) + extends TypeAccumulator[List[NamedType]]: + def maybeAdd(xs: List[NamedType], tp: NamedType): List[NamedType] = if p(tp) then tp :: xs else xs val seen = TypeHashSet() - def apply(x: mutable.Set[NamedType], tp: Type): mutable.Set[NamedType] = - if (seen contains tp) x - else { + def apply(xs: List[NamedType], tp: Type): List[NamedType] = + if seen contains tp then xs + else seen.addEntry(tp) - tp match { + tp match case tp: TypeRef => - foldOver(maybeAdd(x, tp), tp) + foldOver(maybeAdd(xs, tp), tp) case tp: ThisType => - apply(x, tp.tref) + apply(xs, tp.tref) case NoPrefix => - foldOver(x, tp) + foldOver(xs, tp) case tp: TermRef => - apply(foldOver(maybeAdd(x, tp), tp), tp.underlying) + apply(foldOver(maybeAdd(xs, tp), tp), tp.underlying) case tp: AppliedType => - foldOver(x, tp) + foldOver(xs, tp) case TypeBounds(lo, hi) => - if (!excludeLowerBounds) apply(x, lo) - apply(x, hi) + apply(apply(xs, lo), hi) case tp: ParamRef => - apply(x, tp.underlying) + apply(xs, tp.underlying) case tp: ConstantType => - apply(x, tp.underlying) + apply(xs, tp.underlying) case _ => - foldOver(x, tp) - } - } - } + foldOver(xs, tp) + end NamedPartsAccumulator class isGroundAccumulator(using Context) extends TypeAccumulator[Boolean] { def apply(x: Boolean, tp: Type): Boolean = x && { diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 9b380ccf5992..254834930305 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -907,7 +907,7 @@ class Typer extends Namer pt, localSyms(stats1)) } - def escapingRefs(block: Tree, localSyms: => List[Symbol])(using Context): collection.Set[NamedType] = { + def escapingRefs(block: Tree, localSyms: => List[Symbol])(using Context): List[NamedType] = { lazy val locals = localSyms.toSet block.tpe.namedPartsWith(tp => locals.contains(tp.symbol) && !tp.isErroneous) }