Skip to content

Commit d873ae5

Browse files
committed
Introduce a base trait for Candidate and SearchSuccess
This commit does not change the compiler behavior but replaces `compareCandidate` by a more generic `compareAlternatives` that will be useful in the next commit, this required introducing a base trait `RefAndLevel` (not a great name, but I couldn't think of anything better...).
1 parent 55e378d commit d873ae5

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)