@@ -50,8 +50,14 @@ object Implicits:
5050 def implicitName (using Context ): TermName = alias
5151 }
5252
53+ /** Both search candidates and successes are references with a specific nesting level. */
54+ sealed trait RefAndLevel {
55+ def ref : TermRef
56+ def level : Int
57+ }
58+
5359 /** An eligible implicit candidate, consisting of an implicit reference and a nesting level */
54- case class Candidate (implicitRef : ImplicitRef , kind : Candidate .Kind , level : Int ) {
60+ case class Candidate (implicitRef : ImplicitRef , kind : Candidate .Kind , level : Int ) extends RefAndLevel {
5561 def ref : TermRef = implicitRef.underlyingRef
5662
5763 def isExtension = (kind & Candidate .Extension ) != 0
@@ -385,7 +391,8 @@ object Implicits:
385391 * @param level The level where the reference was found
386392 * @param tstate The typer state to be committed if this alternative is chosen
387393 */
388- case class SearchSuccess (tree : Tree , ref : TermRef , level : Int )(val tstate : TyperState , val gstate : GadtConstraint ) extends SearchResult with Showable
394+ case class SearchSuccess (tree : Tree , ref : TermRef , level : Int )(val tstate : TyperState , val gstate : GadtConstraint )
395+ extends SearchResult with RefAndLevel with Showable
389396
390397 /** A failed search */
391398 case class SearchFailure (tree : Tree ) extends SearchResult {
@@ -1124,21 +1131,24 @@ trait Implicits:
11241131 /** Search a list of eligible implicit references */
11251132 private def searchImplicit (eligible : List [Candidate ], contextual : Boolean ): SearchResult =
11261133
1127- /** Compare previous success with reference and level to determine which one would be chosen, if
1128- * an implicit starting with the reference was found.
1134+ /** Compare `alt1` with `alt2` to determine which one should be chosen.
1135+ *
1136+ * @return a number > 0 if `alt1` is preferred over `alt2`
1137+ * a number < 0 if `alt2` is preferred over `alt1`
1138+ * 0 if neither alternative is preferred over the other
11291139 */
1130- def compareCandidate ( prev : SearchSuccess , ref : TermRef , level : Int ): Int =
1131- if (prev .ref eq ref) 0
1132- else if (prev .level != level) prev .level - level
1133- else explore(compare(prev .ref, ref))(using nestedContext())
1140+ def compareAlternatives ( alt1 : RefAndLevel , alt2 : RefAndLevel ): Int =
1141+ if alt1 .ref eq alt2. ref then 0
1142+ else if alt1 .level != alt2. level then alt1 .level - alt2. level
1143+ else explore(compare(alt1 .ref, alt2. ref))(using nestedContext())
11341144
11351145 /** If `alt1` is also a search success, try to disambiguate as follows:
11361146 * - If alt2 is preferred over alt1, pick alt2, otherwise return an
11371147 * ambiguous implicits error.
11381148 */
11391149 def disambiguate (alt1 : SearchResult , alt2 : SearchSuccess ) = alt1 match
11401150 case alt1 : SearchSuccess =>
1141- var diff = compareCandidate (alt1, alt2.ref, alt2.level )
1151+ var diff = compareAlternatives (alt1, alt2)
11421152 assert(diff <= 0 ) // diff > 0 candidates should already have been eliminated in `rank`
11431153 if diff == 0 then
11441154 // Fall back: if both results are extension method applications,
@@ -1166,8 +1176,8 @@ trait Implicits:
11661176 def healAmbiguous (pending : List [Candidate ], fail : SearchFailure ) = {
11671177 val ambi = fail.reason.asInstanceOf [AmbiguousImplicits ]
11681178 val newPending = pending.filter(cand =>
1169- compareCandidate (ambi.alt1, cand.ref, cand.level ) < 0 &&
1170- compareCandidate (ambi.alt2, cand.ref, cand.level ) < 0 )
1179+ compareAlternatives (ambi.alt1, cand) < 0 &&
1180+ compareAlternatives (ambi.alt2, cand) < 0 )
11711181 rank(newPending, fail, Nil ).recoverWith(_ => fail)
11721182 }
11731183
@@ -1210,7 +1220,7 @@ trait Implicits:
12101220 val newPending =
12111221 if (retained eq found) || remaining.isEmpty then remaining
12121222 else remaining.filterConserve(cand =>
1213- compareCandidate (retained, cand.ref, cand.level ) <= 0 )
1223+ compareAlternatives (retained, cand) <= 0 )
12141224 rank(newPending, retained, rfailures)
12151225 case fail : SearchFailure =>
12161226 healAmbiguous(remaining, fail)
0 commit comments