@@ -239,23 +239,20 @@ object Implicits:
239
239
Nil
240
240
else
241
241
val nestedCtx = ctx.fresh.addMode(Mode .TypevarsMissContext )
242
+ val candidates = new mutable.ListBuffer [Candidate ]
243
+ var extensionOnly = true
242
244
243
- def matchingCandidate (ref : ImplicitRef , extensionOnly : Boolean ) : Option [ Candidate ] =
245
+ val tryCandidate = (ref : ImplicitRef ) =>
244
246
var ckind = explore(candidateKind(ref.underlyingRef))(using nestedCtx)
245
247
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
259
256
}
260
257
}
261
258
@@ -265,7 +262,7 @@ object Implicits:
265
262
*/
266
263
class OfTypeImplicits (tp : Type , override val companionRefs : TermRefSet )(initctx : Context ) extends ImplicitRefs (initctx) {
267
264
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 }%, % " )
269
266
@ threadUnsafe lazy val refs : List [ImplicitRef ] = {
270
267
val buf = new mutable.ListBuffer [TermRef ]
271
268
for (companion <- companionRefs) buf ++= companion.implicitMembers
@@ -274,7 +271,7 @@ object Implicits:
274
271
275
272
/** The candidates that are eligible for expected type `tp` */
276
273
@ 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 ) {
278
275
if (refs.nonEmpty && monitored) record(s " check eligible refs in tpe " , refs.length)
279
276
filterMatching(tp)
280
277
}
@@ -283,7 +280,7 @@ object Implicits:
283
280
ref.symbol.exists && ! ref.symbol.is(Private )
284
281
285
282
override def toString : String =
286
- i " OfTypeImplicits( $tp), companions = ${companionRefs.toList }%, %; refs = $refs%, %. "
283
+ i " OfTypeImplicits( $tp), companions = ${companionRefs.showAsList }%, %; refs = $refs%, %. "
287
284
}
288
285
289
286
/** The implicit references coming from the context.
@@ -681,41 +678,41 @@ trait ImplicitRunInfo:
681
678
* - If `T` is some other type, S includes the implicit scopes of all anchors of `T`.
682
679
*/
683
680
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)
687
699
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)
691
712
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)
719
716
end implicitScope
720
717
721
718
protected def reset (): Unit =
@@ -1204,7 +1201,7 @@ trait Implicits:
1204
1201
else disambiguate(found, best) match {
1205
1202
case retained : SearchSuccess =>
1206
1203
val newPending =
1207
- if (retained eq found) remaining
1204
+ if (retained eq found) || remaining.isEmpty then remaining
1208
1205
else remaining.filter(cand =>
1209
1206
compareCandidate(retained, cand.ref, cand.level) <= 0 )
1210
1207
rank(newPending, retained, rfailures)
@@ -1669,7 +1666,7 @@ sealed class TermRefSet(using Context):
1669
1666
if ! prefixes.exists(_ =:= pre) then elems.put(sym, pre :: prefixes)
1670
1667
1671
1668
def ++= (that : TermRefSet ): Unit =
1672
- that.foreach(+= )
1669
+ if ! that.isEmpty then that.foreach(+= )
1673
1670
1674
1671
def foreach [U ](f : TermRef => U ): Unit =
1675
1672
elems.forEach((sym : TermSymbol , prefixes : Type | List [Type ]) =>
@@ -1678,13 +1675,13 @@ sealed class TermRefSet(using Context):
1678
1675
case prefixes : List [Type ] => prefixes.foreach(pre => f(TermRef (pre, sym))))
1679
1676
1680
1677
// used only for debugging
1681
- def toList : List [TermRef ] = {
1678
+ def showAsList : List [TermRef ] = {
1682
1679
val buffer = new mutable.ListBuffer [TermRef ]
1683
1680
foreach(tr => buffer += tr)
1684
1681
buffer.toList
1685
1682
}
1686
1683
1687
- override def toString = toList .toString
1684
+ override def toString = showAsList .toString
1688
1685
1689
1686
object TermRefSet :
1690
1687
0 commit comments