@@ -419,6 +419,12 @@ object Implicits:
419419 sealed abstract class SearchResult extends Showable {
420420 def tree : Tree
421421 def toText (printer : Printer ): Text = printer.toText(this )
422+
423+ /** The references that were found, there can be two of them in the case
424+ * of an AmbiguousImplicits failure
425+ */
426+ def found : List [TermRef ]
427+
422428 def recoverWith (other : SearchFailure => SearchResult ): SearchResult = this match {
423429 case _ : SearchSuccess => this
424430 case fail : SearchFailure => other(fail)
@@ -434,13 +440,17 @@ object Implicits:
434440 * @param tstate The typer state to be committed if this alternative is chosen
435441 */
436442 case class SearchSuccess (tree : Tree , ref : TermRef , level : Int , isExtension : Boolean = false )(val tstate : TyperState , val gstate : GadtConstraint )
437- extends SearchResult with RefAndLevel with Showable
443+ extends SearchResult with RefAndLevel with Showable :
444+ final def found = ref :: Nil
438445
439446 /** A failed search */
440447 case class SearchFailure (tree : Tree ) extends SearchResult {
441448 require(tree.tpe.isInstanceOf [SearchFailureType ], s " unexpected type for ${tree}" )
442449 final def isAmbiguous : Boolean = tree.tpe.isInstanceOf [AmbiguousImplicits | TooUnspecific ]
443450 final def reason : SearchFailureType = tree.tpe.asInstanceOf [SearchFailureType ]
451+ final def found = tree.tpe match
452+ case tpe : AmbiguousImplicits => tpe.alt1.ref :: tpe.alt2.ref :: Nil
453+ case _ => Nil
444454 }
445455
446456 object SearchFailure {
@@ -1290,6 +1300,12 @@ trait Implicits:
12901300 /** Search a list of eligible implicit references */
12911301 private def searchImplicit (eligible : List [Candidate ], contextual : Boolean ): SearchResult =
12921302
1303+ // A map that associates a priority change warning (between -source 3.4 and 3.6)
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 )]()
1308+
12931309 /** Compare `alt1` with `alt2` to determine which one should be chosen.
12941310 *
12951311 * @return a number > 0 if `alt1` is preferred over `alt2`
@@ -1306,6 +1322,8 @@ trait Implicits:
13061322 */
13071323 def compareAlternatives (alt1 : RefAndLevel , alt2 : RefAndLevel ): Int =
13081324 def comp (using Context ) = explore(compare(alt1.ref, alt2.ref, preferGeneral = true ))
1325+ def warn (msg : Message ) =
1326+ priorityChangeWarnings += ((alt1.ref, alt2.ref, msg))
13091327 if alt1.ref eq alt2.ref then 0
13101328 else if alt1.level != alt2.level then alt1.level - alt2.level
13111329 else
@@ -1319,16 +1337,16 @@ trait Implicits:
13191337 case 1 => " the first alternative"
13201338 case _ => " none - it's ambiguous"
13211339 if sv.stable == SourceVersion .`3.5` then
1322- report.warning (
1340+ warn (
13231341 em """ Given search preference for $pt between alternatives ${alt1.ref} and ${alt2.ref} will change
13241342 |Current choice : ${choice(prev)}
1325- |New choice from Scala 3.6: ${choice(cmp)}""" , srcPos )
1343+ |New choice from Scala 3.6: ${choice(cmp)}""" )
13261344 prev
13271345 else
1328- report.warning (
1346+ warn (
13291347 em """ Change in given search preference for $pt between alternatives ${alt1.ref} and ${alt2.ref}
13301348 |Previous choice : ${choice(prev)}
1331- |New choice from Scala 3.6: ${choice(cmp)}""" , srcPos )
1349+ |New choice from Scala 3.6: ${choice(cmp)}""" )
13321350 cmp
13331351 else cmp
13341352 else cmp
@@ -1423,7 +1441,11 @@ trait Implicits:
14231441 // need a candidate better than `cand`
14241442 healAmbiguous(fail, newCand =>
14251443 compareAlternatives(newCand, cand) > 0 )
1426- else rank(remaining, found, fail :: rfailures)
1444+ else
1445+ // keep only warnings that don't involve the failed candidate reference
1446+ priorityChangeWarnings.filterInPlace: (ref1, ref2, _) =>
1447+ ref1 != cand.ref && ref2 != cand.ref
1448+ rank(remaining, found, fail :: rfailures)
14271449 case best : SearchSuccess =>
14281450 if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent)
14291451 best
@@ -1578,7 +1600,11 @@ trait Implicits:
15781600 validateOrdering(ord)
15791601 throw ex
15801602
1581- rank(sort(eligible), NoMatchingImplicitsFailure , Nil )
1603+ 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
1606+ report.warning(msg, srcPos)
1607+ result
15821608 end searchImplicit
15831609
15841610 def isUnderSpecifiedArgument (tp : Type ): Boolean =
0 commit comments