@@ -50,8 +50,14 @@ object Implicits:
50
50
def implicitName (using Context ): TermName = alias
51
51
}
52
52
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
+
53
59
/** 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 {
55
61
def ref : TermRef = implicitRef.underlyingRef
56
62
57
63
def isExtension = (kind & Candidate .Extension ) != 0
@@ -385,7 +391,8 @@ object Implicits:
385
391
* @param level The level where the reference was found
386
392
* @param tstate The typer state to be committed if this alternative is chosen
387
393
*/
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
389
396
390
397
/** A failed search */
391
398
case class SearchFailure (tree : Tree ) extends SearchResult {
@@ -1124,21 +1131,24 @@ trait Implicits:
1124
1131
/** Search a list of eligible implicit references */
1125
1132
private def searchImplicit (eligible : List [Candidate ], contextual : Boolean ): SearchResult =
1126
1133
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
1129
1139
*/
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())
1134
1144
1135
1145
/** If `alt1` is also a search success, try to disambiguate as follows:
1136
1146
* - If alt2 is preferred over alt1, pick alt2, otherwise return an
1137
1147
* ambiguous implicits error.
1138
1148
*/
1139
1149
def disambiguate (alt1 : SearchResult , alt2 : SearchSuccess ) = alt1 match
1140
1150
case alt1 : SearchSuccess =>
1141
- var diff = compareCandidate (alt1, alt2.ref, alt2.level )
1151
+ var diff = compareAlternatives (alt1, alt2)
1142
1152
assert(diff <= 0 ) // diff > 0 candidates should already have been eliminated in `rank`
1143
1153
if diff == 0 then
1144
1154
// Fall back: if both results are extension method applications,
@@ -1166,8 +1176,8 @@ trait Implicits:
1166
1176
def healAmbiguous (pending : List [Candidate ], fail : SearchFailure ) = {
1167
1177
val ambi = fail.reason.asInstanceOf [AmbiguousImplicits ]
1168
1178
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 )
1171
1181
rank(newPending, fail, Nil ).recoverWith(_ => fail)
1172
1182
}
1173
1183
@@ -1210,7 +1220,7 @@ trait Implicits:
1210
1220
val newPending =
1211
1221
if (retained eq found) || remaining.isEmpty then remaining
1212
1222
else remaining.filterConserve(cand =>
1213
- compareCandidate (retained, cand.ref, cand.level ) <= 0 )
1223
+ compareAlternatives (retained, cand) <= 0 )
1214
1224
rank(newPending, retained, rfailures)
1215
1225
case fail : SearchFailure =>
1216
1226
healAmbiguous(remaining, fail)
0 commit comments