@@ -1305,6 +1305,9 @@ trait Implicits:
1305
1305
// message if one of the critical candidates is part of the result of the implicit search.
1306
1306
val priorityChangeWarnings = mutable.ListBuffer [(/* critical:*/ List [TermRef ], Message )]()
1307
1307
1308
+ def isWarnPriorityChangeVersion (sv : SourceVersion ): Boolean =
1309
+ sv.stable == SourceVersion .`3.5` || sv == SourceVersion .`3.6-migration`
1310
+
1308
1311
/** Compare `alt1` with `alt2` to determine which one should be chosen.
1309
1312
*
1310
1313
* @return a number > 0 if `alt1` is preferred over `alt2`
@@ -1321,25 +1324,21 @@ trait Implicits:
1321
1324
* @param disambiguate The call is used to disambiguate two successes, not for ranking.
1322
1325
* When ranking, we are always filtering out either > 0 or <= 0 results.
1323
1326
* In each case a priority change from 0 to -1 or vice versa makes no difference.
1324
- * @param only2ndCritical If true only the second alternative is critical in case
1325
- * of a priority change.
1326
1327
*/
1327
- def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel , disambiguate : Boolean = false , only2ndCritical : Boolean = false ): Int =
1328
+ def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel , disambiguate : Boolean = false ): Int =
1328
1329
def comp (using Context ) = explore(compare(alt1.ref, alt2.ref, preferGeneral = true ))
1329
1330
if alt1.ref eq alt2.ref then 0
1330
1331
else if alt1.level != alt2.level then alt1.level - alt2.level
1331
1332
else
1332
1333
var cmp = comp(using searchContext())
1333
1334
val sv = Feature .sourceVersion
1334
- if sv.stable == SourceVersion .`3.5` || sv == SourceVersion .`3.6-migration` then
1335
+ if isWarnPriorityChangeVersion(sv) then
1335
1336
val prev = comp(using searchContext().addMode(Mode .OldImplicitResolution ))
1336
- if cmp != prev then
1337
+ if disambiguate && cmp != prev then
1337
1338
def warn (msg : Message ) =
1338
- if disambiguate || cmp > 0 || prev > 0 then
1339
- val critical =
1340
- if only2ndCritical then alt2.ref :: Nil
1341
- else alt1.ref :: alt2.ref :: Nil
1342
- priorityChangeWarnings += ((critical, msg))
1339
+ val critical = alt1.ref :: alt2.ref :: Nil
1340
+ priorityChangeWarnings += ((critical, msg))
1341
+ implicits.println(i " PRIORITY CHANGE ${alt1.ref}, ${alt2.ref}, $disambiguate" )
1343
1342
def choice (c : Int ) = c match
1344
1343
case - 1 => " the second alternative"
1345
1344
case 1 => " the first alternative"
@@ -1356,7 +1355,9 @@ trait Implicits:
1356
1355
|Previous choice : ${choice(prev)}
1357
1356
|New choice from Scala 3.6: ${choice(cmp)}""" )
1358
1357
cmp
1359
- 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.
1360
1361
else cmp
1361
1362
end compareAlternatives
1362
1363
@@ -1367,7 +1368,8 @@ trait Implicits:
1367
1368
def disambiguate (alt1 : SearchResult , alt2 : SearchSuccess ) = alt1 match
1368
1369
case alt1 : SearchSuccess =>
1369
1370
var diff = compareAlternatives(alt1, alt2, disambiguate = true )
1370
- assert(diff <= 0 ) // diff > 0 candidates should already have been eliminated in `rank`
1371
+ assert(diff <= 0 || isWarnPriorityChangeVersion(Feature .sourceVersion))
1372
+ // diff > 0 candidates should already have been eliminated in `rank`
1371
1373
if diff == 0 && alt1.ref =:= alt2.ref then
1372
1374
diff = 1 // See i12951 for a test where this happens
1373
1375
else if diff == 0 && alt2.isExtension then
@@ -1461,16 +1463,7 @@ trait Implicits:
1461
1463
case retained : SearchSuccess =>
1462
1464
val newPending =
1463
1465
if (retained eq found) || remaining.isEmpty then remaining
1464
- else remaining.filterConserve(cand =>
1465
- compareAlternatives(retained, cand, only2ndCritical = true ) <= 0 )
1466
- // Here we drop some pending alternatives but retain in each case
1467
- // `retained`. Therefore, it's a priorty change only if the
1468
- // second alternative appears in the final search result. Otherwise
1469
- // we have the following scenario:
1470
- // - 1st alternative, but not snd appears in final result
1471
- // - Hence, snd was eliminated either here, or otherwise by a direct
1472
- // comparison later.
1473
- // - Hence, no change in resolution.
1466
+ else remaining.filterConserve(newCand => compareAlternatives(newCand, retained) >= 0 )
1474
1467
rank(newPending, retained, rfailures)
1475
1468
case fail : SearchFailure =>
1476
1469
// The ambiguity happened in the current search: to recover we
0 commit comments