@@ -1302,9 +1302,8 @@ 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 )]()
13081307
13091308 /** Compare `alt1` with `alt2` to determine which one should be chosen.
13101309 *
@@ -1319,11 +1318,16 @@ trait Implicits:
13191318 * return new result with preferGeneral = true
13201319 * 3.6 and higher: compare with preferGeneral = true
13211320 *
1321+ * @param only2ndCritical If true only the second alternative is critical in case
1322+ * of a priority change.
13221323 */
1323- def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel ): Int =
1324+ def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel , only2ndCritical : Boolean = false ): Int =
13241325 def comp (using Context ) = explore(compare(alt1.ref, alt2.ref, preferGeneral = true ))
13251326 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))
13271331 if alt1.ref eq alt2.ref then 0
13281332 else if alt1.level != alt2.level then alt1.level - alt2.level
13291333 else
@@ -1443,8 +1447,8 @@ trait Implicits:
14431447 compareAlternatives(newCand, cand) > 0 )
14441448 else
14451449 // 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)
14481452 rank(remaining, found, fail :: rfailures)
14491453 case best : SearchSuccess =>
14501454 if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent)
@@ -1454,7 +1458,15 @@ trait Implicits:
14541458 val newPending =
14551459 if (retained eq found) || remaining.isEmpty then remaining
14561460 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.
14581470 rank(newPending, retained, rfailures)
14591471 case fail : SearchFailure =>
14601472 // The ambiguity happened in the current search: to recover we
@@ -1601,8 +1613,8 @@ trait Implicits:
16011613 throw ex
16021614
16031615 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
16061618 report.warning(msg, srcPos)
16071619 result
16081620 end searchImplicit
0 commit comments