diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index df5a6f0bd2d9..6f17de5cdc44 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1439,9 +1439,14 @@ trait Implicits: * candidate that is strictly better than the failed candidate(s). * If no such candidate is found, we propagate the ambiguity. */ - def healAmbiguous(fail: SearchFailure, betterThanFailed: Candidate => Boolean) = - val newPending = remaining.filter(betterThanFailed) - rank(newPending, fail, Nil).recoverWith(_ => fail) + def healAmbiguous(fail: SearchFailure, ambiguousCands: List[RefAndLevel]) = + def betterThanAll(newCand: RefAndLevel, disambiguate: Boolean): Boolean = + ambiguousCands.forall(compareAlternatives(newCand, _, disambiguate) > 0) + + val newPending = remaining.filter(betterThanAll(_, disambiguate = false)) + rank(newPending, fail, Nil) match + case found: SearchSuccess if betterThanAll(found, disambiguate = true) => found + case _ => fail negateIfNot(tryImplicit(cand, contextual)) match { case fail: SearchFailure => @@ -1456,8 +1461,7 @@ trait Implicits: else // The ambiguity happened in a nested search: to recover we // need a candidate better than `cand` - healAmbiguous(fail, newCand => - compareAlternatives(newCand, cand) > 0) + healAmbiguous(fail, cand :: Nil) else // keep only warnings that don't involve the failed candidate reference priorityChangeWarnings.filterInPlace: (critical, _) => @@ -1476,9 +1480,7 @@ trait Implicits: // The ambiguity happened in the current search: to recover we // need a candidate better than the two ambiguous alternatives. val ambi = fail.reason.asInstanceOf[AmbiguousImplicits] - healAmbiguous(fail, newCand => - compareAlternatives(newCand, ambi.alt1) > 0 && - compareAlternatives(newCand, ambi.alt2) > 0) + healAmbiguous(fail, ambi.alt1 :: ambi.alt2 :: Nil) } } case nil => diff --git a/tests/neg/i21212.check b/tests/neg/i21212.check deleted file mode 100644 index 5d9fe7728cbc..000000000000 --- a/tests/neg/i21212.check +++ /dev/null @@ -1,4 +0,0 @@ --- [E172] Type Error: tests/neg/i21212.scala:8:52 ---------------------------------------------------------------------- -8 | def test2(using a2: A)(implicit b2: B) = summon[A] // error: ambiguous - | ^ - |Ambiguous given instances: both parameter b2 and parameter a2 match type Minimization.A of parameter x of method summon in object Predef diff --git a/tests/neg/i21212.scala b/tests/neg/i21212.scala deleted file mode 100644 index 99e4c44f9489..000000000000 --- a/tests/neg/i21212.scala +++ /dev/null @@ -1,11 +0,0 @@ -//> using options -source 3.7 -object Minimization: - - trait A - trait B extends A - - def test1(using a1: A)(using b1: B) = summon[A] // picks (most general) a1 - def test2(using a2: A)(implicit b2: B) = summon[A] // error: ambiguous - def test3(implicit a3: A, b3: B) = summon[A] // picks (most specific) b3 - -end Minimization diff --git a/tests/pos/i21212.scala b/tests/pos/i21212.scala index 1a1f2e35819a..9df8a37437fe 100644 --- a/tests/pos/i21212.scala +++ b/tests/pos/i21212.scala @@ -20,3 +20,14 @@ class UsingArguments[F[_]](using Temporal[F])(using err: MonadError[F, Throwable val bool: F[Boolean] = ??? def works = toFunctorOps(bool).map(_ => ()) // warns under -source:3.5 + +object Minimization: + + trait A + trait B extends A + + def test1(using a1: A)(using b1: B) = summon[A] // picks (most general) a1 + def test2(using a2: A)(implicit b2: B) = summon[A] // picks (most general) a2, was ambiguous + def test3(implicit a3: A, b3: B) = summon[A] // picks (most specific) b3 + +end Minimization \ No newline at end of file