@@ -1302,9 +1302,8 @@ trait Implicits:
1302
1302
1303
1303
// A map that associates a priority change warning (between -source 3.4 and 3.6)
1304
1304
// 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 )]()
1308
1307
1309
1308
/** Compare `alt1` with `alt2` to determine which one should be chosen.
1310
1309
*
@@ -1319,11 +1318,16 @@ trait Implicits:
1319
1318
* return new result with preferGeneral = true
1320
1319
* 3.6 and higher: compare with preferGeneral = true
1321
1320
*
1321
+ * @param only2ndCritical If true only the second alternative is critical in case
1322
+ * of a priority change.
1322
1323
*/
1323
- def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel ): Int =
1324
+ def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel , only2ndCritical : Boolean = false ): Int =
1324
1325
def comp (using Context ) = explore(compare(alt1.ref, alt2.ref, preferGeneral = true ))
1325
1326
def warn (msg : Message ) =
1326
- priorityChangeWarnings += ((alt1.ref, alt2.ref, msg))
1327
+ val critical =
1328
+ if only2ndCritical then alt2.ref :: Nil
1329
+ else alt1.ref :: alt2.ref :: Nil
1330
+ priorityChangeWarnings += ((critical, msg))
1327
1331
if alt1.ref eq alt2.ref then 0
1328
1332
else if alt1.level != alt2.level then alt1.level - alt2.level
1329
1333
else
@@ -1443,8 +1447,8 @@ trait Implicits:
1443
1447
compareAlternatives(newCand, cand) > 0 )
1444
1448
else
1445
1449
// keep only warnings that don't involve the failed candidate reference
1446
- priorityChangeWarnings.filterInPlace: (ref1, ref2 , _) =>
1447
- ref1 != cand.ref && ref2 != cand.ref
1450
+ priorityChangeWarnings.filterInPlace: (critical , _) =>
1451
+ ! critical.contains( cand.ref)
1448
1452
rank(remaining, found, fail :: rfailures)
1449
1453
case best : SearchSuccess =>
1450
1454
if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent)
@@ -1454,7 +1458,15 @@ trait Implicits:
1454
1458
val newPending =
1455
1459
if (retained eq found) || remaining.isEmpty then remaining
1456
1460
else remaining.filterConserve(cand =>
1457
- compareAlternatives(retained, cand) <= 0 )
1461
+ compareAlternatives(retained, cand, only2ndCritical = true ) <= 0 )
1462
+ // Here we drop some pending alternatives but retain in each case
1463
+ // `retained`. Therefore, it's a priorty change only if the
1464
+ // second alternative appears in the final search result. Otherwise
1465
+ // we have the following scenario:
1466
+ // - 1st alternative, bit not snd appears in final result
1467
+ // - Hence, snd was eliminated either here, or otherwise by a direct
1468
+ // comparison later.
1469
+ // - Hence, no change in resolution.
1458
1470
rank(newPending, retained, rfailures)
1459
1471
case fail : SearchFailure =>
1460
1472
// The ambiguity happened in the current search: to recover we
@@ -1601,8 +1613,8 @@ trait Implicits:
1601
1613
throw ex
1602
1614
1603
1615
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
1616
+ for (critical , msg) <- priorityChangeWarnings do
1617
+ if result.found.exists(critical.contains(_) ) then
1606
1618
report.warning(msg, srcPos)
1607
1619
result
1608
1620
end searchImplicit
0 commit comments