@@ -1302,9 +1302,11 @@ trait Implicits:
13021302
13031303 // A map that associates a priority change warning (between -source 3.4 and 3.6)
13041304 // with the candidate refs mentioned in the warning. We report the associated
1305- // message if both candidates qualify in tryImplicit and at least one of the candidates
1306- // is part of the result of the implicit search.
1307- val priorityChangeWarnings = mutable.ListBuffer [(TermRef , TermRef , Message )]()
1305+ // message if one of the critical candidates is part of the result of the implicit search.
1306+ val priorityChangeWarnings = mutable.ListBuffer [(/* critical:*/ List [TermRef ], Message )]()
1307+
1308+ def isWarnPriorityChangeVersion (sv : SourceVersion ): Boolean =
1309+ sv.stable == SourceVersion .`3.5` || sv == SourceVersion .`3.6-migration`
13081310
13091311 /** Compare `alt1` with `alt2` to determine which one should be chosen.
13101312 *
@@ -1319,19 +1321,24 @@ trait Implicits:
13191321 * return new result with preferGeneral = true
13201322 * 3.6 and higher: compare with preferGeneral = true
13211323 *
1324+ * @param disambiguate The call is used to disambiguate two successes, not for ranking.
1325+ * When ranking, we are always filtering out either > 0 or <= 0 results.
1326+ * In each case a priority change from 0 to -1 or vice versa makes no difference.
13221327 */
1323- def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel ): Int =
1328+ def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel , disambiguate : Boolean = false ): Int =
13241329 def comp (using Context ) = explore(compare(alt1.ref, alt2.ref, preferGeneral = true ))
1325- def warn (msg : Message ) =
1326- priorityChangeWarnings += ((alt1.ref, alt2.ref, msg))
13271330 if alt1.ref eq alt2.ref then 0
13281331 else if alt1.level != alt2.level then alt1.level - alt2.level
13291332 else
13301333 var cmp = comp(using searchContext())
13311334 val sv = Feature .sourceVersion
1332- if sv.stable == SourceVersion .`3.5` || sv == SourceVersion .`3.6-migration` then
1335+ if isWarnPriorityChangeVersion(sv) then
13331336 val prev = comp(using searchContext().addMode(Mode .OldImplicitResolution ))
1334- if cmp != prev then
1337+ if disambiguate && cmp != prev then
1338+ def warn (msg : Message ) =
1339+ val critical = alt1.ref :: alt2.ref :: Nil
1340+ priorityChangeWarnings += ((critical, msg))
1341+ implicits.println(i " PRIORITY CHANGE ${alt1.ref}, ${alt2.ref}, $disambiguate" )
13351342 def choice (c : Int ) = c match
13361343 case - 1 => " the second alternative"
13371344 case 1 => " the first alternative"
@@ -1348,7 +1355,9 @@ trait Implicits:
13481355 |Previous choice : ${choice(prev)}
13491356 |New choice from Scala 3.6: ${choice(cmp)}""" )
13501357 cmp
1351- else cmp
1358+ else cmp max prev
1359+ // When ranking, we keep the better of cmp and prev, which ends up retaining a candidate
1360+ // if it is retained in either version.
13521361 else cmp
13531362 end compareAlternatives
13541363
@@ -1358,8 +1367,9 @@ trait Implicits:
13581367 */
13591368 def disambiguate (alt1 : SearchResult , alt2 : SearchSuccess ) = alt1 match
13601369 case alt1 : SearchSuccess =>
1361- var diff = compareAlternatives(alt1, alt2)
1362- assert(diff <= 0 ) // diff > 0 candidates should already have been eliminated in `rank`
1370+ var diff = compareAlternatives(alt1, alt2, disambiguate = true )
1371+ assert(diff <= 0 || isWarnPriorityChangeVersion(Feature .sourceVersion))
1372+ // diff > 0 candidates should already have been eliminated in `rank`
13631373 if diff == 0 && alt1.ref =:= alt2.ref then
13641374 diff = 1 // See i12951 for a test where this happens
13651375 else if diff == 0 && alt2.isExtension then
@@ -1443,8 +1453,8 @@ trait Implicits:
14431453 compareAlternatives(newCand, cand) > 0 )
14441454 else
14451455 // keep only warnings that don't involve the failed candidate reference
1446- priorityChangeWarnings.filterInPlace: (ref1, ref2 , _) =>
1447- ref1 != cand.ref && ref2 != cand.ref
1456+ priorityChangeWarnings.filterInPlace: (critical , _) =>
1457+ ! critical.contains( cand.ref)
14481458 rank(remaining, found, fail :: rfailures)
14491459 case best : SearchSuccess =>
14501460 if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent)
@@ -1453,8 +1463,7 @@ trait Implicits:
14531463 case retained : SearchSuccess =>
14541464 val newPending =
14551465 if (retained eq found) || remaining.isEmpty then remaining
1456- else remaining.filterConserve(cand =>
1457- compareAlternatives(retained, cand) <= 0 )
1466+ else remaining.filterConserve(newCand => compareAlternatives(newCand, retained) >= 0 )
14581467 rank(newPending, retained, rfailures)
14591468 case fail : SearchFailure =>
14601469 // The ambiguity happened in the current search: to recover we
@@ -1601,8 +1610,8 @@ trait Implicits:
16011610 throw ex
16021611
16031612 val result = rank(sort(eligible), NoMatchingImplicitsFailure , Nil )
1604- for (ref1, ref2 , msg) <- priorityChangeWarnings do
1605- if result.found.exists(ref => ref == ref1 || ref == ref2 ) then
1613+ for (critical , msg) <- priorityChangeWarnings do
1614+ if result.found.exists(critical.contains(_) ) then
16061615 report.warning(msg, srcPos)
16071616 result
16081617 end searchImplicit
0 commit comments