@@ -239,23 +239,20 @@ object Implicits:
239239 Nil
240240 else
241241 val nestedCtx = ctx.fresh.addMode(Mode .TypevarsMissContext )
242+ val candidates = new mutable.ListBuffer [Candidate ]
243+ var extensionOnly = true
242244
243- def matchingCandidate (ref : ImplicitRef , extensionOnly : Boolean ) : Option [ Candidate ] =
245+ val tryCandidate = (ref : ImplicitRef ) =>
244246 var ckind = explore(candidateKind(ref.underlyingRef))(using nestedCtx)
245247 if extensionOnly then ckind &= Candidate .Extension
246- if ckind == Candidate .None then None
247- else Some (new Candidate (ref, ckind, level))
248-
249- val extensionCandidates =
250- if considerExtension then
251- companionRefs.toList
252- .filterConserve(! _.symbol.isOneOf(GivenOrImplicit )) // implicit objects are already in `refs`
253- .flatMap(matchingCandidate(_, extensionOnly = true ))
254- else
255- Nil
256- val implicitCandidates =
257- refs.flatMap(matchingCandidate(_, extensionOnly = false ))
258- extensionCandidates ::: implicitCandidates
248+ if ckind != Candidate .None then
249+ candidates += Candidate (ref, ckind, level)
250+
251+ if considerExtension then
252+ companionRefs.foreach(tryCandidate)
253+ extensionOnly = false
254+ refs.foreach(tryCandidate)
255+ candidates.toList
259256 }
260257 }
261258
@@ -265,7 +262,7 @@ object Implicits:
265262 */
266263 class OfTypeImplicits (tp : Type , override val companionRefs : TermRefSet )(initctx : Context ) extends ImplicitRefs (initctx) {
267264 assert(initctx.typer != null )
268- implicits.println(i " implicit scope of type $tp = ${companionRefs.toList }%, % " )
265+ implicits.println(i " implicit scope of type $tp = ${companionRefs.showAsList }%, % " )
269266 @ threadUnsafe lazy val refs : List [ImplicitRef ] = {
270267 val buf = new mutable.ListBuffer [TermRef ]
271268 for (companion <- companionRefs) buf ++= companion.implicitMembers
@@ -274,7 +271,7 @@ object Implicits:
274271
275272 /** The candidates that are eligible for expected type `tp` */
276273 @ threadUnsafe lazy val eligible : List [Candidate ] =
277- trace(i " eligible( $tp), companions = ${companionRefs.toList }%, % " , implicitsDetailed, show = true ) {
274+ trace(i " eligible( $tp), companions = ${companionRefs.showAsList }%, % " , implicitsDetailed, show = true ) {
278275 if (refs.nonEmpty && monitored) record(s " check eligible refs in tpe " , refs.length)
279276 filterMatching(tp)
280277 }
@@ -283,7 +280,7 @@ object Implicits:
283280 ref.symbol.exists && ! ref.symbol.is(Private )
284281
285282 override def toString : String =
286- i " OfTypeImplicits( $tp), companions = ${companionRefs.toList }%, %; refs = $refs%, %. "
283+ i " OfTypeImplicits( $tp), companions = ${companionRefs.showAsList }%, %; refs = $refs%, %. "
287284 }
288285
289286 /** The implicit references coming from the context.
@@ -681,41 +678,41 @@ trait ImplicitRunInfo:
681678 * - If `T` is some other type, S includes the implicit scopes of all anchors of `T`.
682679 */
683680 def implicitScope (tp : Type )(using Context ): OfTypeImplicits =
684- object liftToAnchors extends TypeMap :
685- override def stopAtStatic = true
686- private val seen = TypeHashSet ()
681+ implicitScopeCache.get(tp) match
682+ case Some (is) => is
683+ case None =>
684+ record(i " implicitScope " )
685+ val liftToAnchors = new TypeMap :
686+ override def stopAtStatic = true
687+ private val seen = TypeHashSet ()
688+
689+ def applyToUnderlying (t : TypeProxy ) =
690+ if seen.contains(t) then
691+ WildcardType
692+ else
693+ seen.addEntry(t)
694+ t.underlying match
695+ case TypeBounds (lo, hi) =>
696+ if defn.isBottomTypeAfterErasure(lo) then apply(hi)
697+ else AndType .make(apply(lo), apply(hi))
698+ case u => apply(u)
687699
688- def applyToUnderlying (t : TypeProxy ) =
689- if seen.contains(t) then
690- WildcardType
700+ def apply (t : Type ) = t.dealias match
701+ case t : TypeRef =>
702+ if t.symbol.isClass || isAnchor(t.symbol) then t else applyToUnderlying(t)
703+ case t : TypeVar => apply(t.underlying)
704+ case t : ParamRef => applyToUnderlying(t)
705+ case t : ConstantType => apply(t.underlying)
706+ case t => mapOver(t)
707+ end liftToAnchors
708+ val liftedTp = liftToAnchors(tp)
709+ if liftedTp eq tp then
710+ record(i " implicitScope unlifted " )
711+ computeIScope(tp)
691712 else
692- seen.addEntry(t)
693- t.underlying match
694- case TypeBounds (lo, hi) =>
695- if defn.isBottomTypeAfterErasure(lo) then apply(hi)
696- else AndType .make(apply(lo), apply(hi))
697- case u => apply(u)
698-
699- def apply (t : Type ) = t.dealias match
700- case t : TypeRef =>
701- if t.symbol.isClass || isAnchor(t.symbol) then t else applyToUnderlying(t)
702- case t : TypeVar => apply(t.underlying)
703- case t : ParamRef => applyToUnderlying(t)
704- case t : ConstantType => apply(t.underlying)
705- case t => mapOver(t)
706- end liftToAnchors
707-
708- record(i " implicitScope " )
709- implicitScopeCache.getOrElse(tp, {
710- val liftedTp = liftToAnchors(tp)
711- if liftedTp eq tp then
712- record(i " implicitScope unlifted " )
713- computeIScope(tp)
714- else
715- record(i " implicitScope lifted " )
716- val liftedIScope = implicitScopeCache.getOrElse(liftedTp, computeIScope(liftedTp))
717- OfTypeImplicits (tp, liftedIScope.companionRefs)(runContext)
718- })
713+ record(i " implicitScope lifted " )
714+ val liftedIScope = implicitScopeCache.getOrElse(liftedTp, computeIScope(liftedTp))
715+ OfTypeImplicits (tp, liftedIScope.companionRefs)(runContext)
719716 end implicitScope
720717
721718 protected def reset (): Unit =
@@ -1204,7 +1201,7 @@ trait Implicits:
12041201 else disambiguate(found, best) match {
12051202 case retained : SearchSuccess =>
12061203 val newPending =
1207- if (retained eq found) remaining
1204+ if (retained eq found) || remaining.isEmpty then remaining
12081205 else remaining.filter(cand =>
12091206 compareCandidate(retained, cand.ref, cand.level) <= 0 )
12101207 rank(newPending, retained, rfailures)
@@ -1669,7 +1666,7 @@ sealed class TermRefSet(using Context):
16691666 if ! prefixes.exists(_ =:= pre) then elems.put(sym, pre :: prefixes)
16701667
16711668 def ++= (that : TermRefSet ): Unit =
1672- that.foreach(+= )
1669+ if ! that.isEmpty then that.foreach(+= )
16731670
16741671 def foreach [U ](f : TermRef => U ): Unit =
16751672 elems.forEach((sym : TermSymbol , prefixes : Type | List [Type ]) =>
@@ -1678,13 +1675,13 @@ sealed class TermRefSet(using Context):
16781675 case prefixes : List [Type ] => prefixes.foreach(pre => f(TermRef (pre, sym))))
16791676
16801677 // used only for debugging
1681- def toList : List [TermRef ] = {
1678+ def showAsList : List [TermRef ] = {
16821679 val buffer = new mutable.ListBuffer [TermRef ]
16831680 foreach(tr => buffer += tr)
16841681 buffer.toList
16851682 }
16861683
1687- override def toString = toList .toString
1684+ override def toString = showAsList .toString
16881685
16891686object TermRefSet :
16901687
0 commit comments