From 26290f642cf380bc41c6831ee90c5e3904140f04 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 8 May 2024 19:48:38 +0200 Subject: [PATCH] Bring back ambiguity filter when we report an implicit not found error This reverts one part of #20261. When we fail with both an ambiguity on one implicit argument and another error on another argument we prefer the other error. I added a comment why this is needed. Fixes #20344 [Cherry-picked 863077c8ec76d7e3ecc57744b8584ccd8d2c241b] --- .../src/dotty/tools/dotc/typer/Typer.scala | 9 +++++- tests/pos/i20344.scala | 28 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i20344.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 5379e70914c7..29d0a381e893 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3810,7 +3810,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer * `SearchFailureType`. */ def issueErrors(fun: Tree, args: List[Tree]): Tree = - def firstFailure = args.tpes.find(_.isInstanceOf[SearchFailureType]).getOrElse(NoType) + // Prefer other errors over ambiguities. If nested in outer searches a missing + // implicit can be healed by simply dropping this alternative and tryng something + // else. But an ambiguity is sticky and propagates outwards. If we have both + // a missing implicit on one argument and an ambiguity on another the whole + // branch should be classified as a missing implicit. + val firstNonAmbiguous = args.tpes.find(tp => tp.isError && !tp.isInstanceOf[AmbiguousImplicits]) + def firstError = args.tpes.find(_.isInstanceOf[SearchFailureType]).getOrElse(NoType) + def firstFailure = firstNonAmbiguous.getOrElse(firstError) val errorType = firstFailure match case tp: AmbiguousImplicits => diff --git a/tests/pos/i20344.scala b/tests/pos/i20344.scala new file mode 100644 index 000000000000..d3b2a060d6e2 --- /dev/null +++ b/tests/pos/i20344.scala @@ -0,0 +1,28 @@ +trait Monad[F[_]] extends Invariant[F] + +trait Invariant[F[_]] +object Invariant: + implicit def catsInstancesForList: Monad[List] = ??? + implicit def catsInstancesForVector: Monad[Vector] = ??? + +trait Shrink[T] +object Shrink extends ShrinkLowPriorityImplicits: + trait Buildable[T,C] + implicit def shrinkContainer[C[_],T](implicit v: C[T] => Traversable[T], s: Shrink[T], b: Buildable[T,C[T]]): Shrink[C[T]] = ??? +trait ShrinkLowPriorityImplicits: + implicit def shrinkAny[T]: Shrink[T] = ??? + +trait Distribution[F[_], -P, X] extends (P => F[X]) +type GenBeta[A, B, X] = [F[_]] =>> Distribution[F, Beta.Params[A, B], X] +type Beta[R] = [F[_]] =>> GenBeta[R, R, R][F] + +object Beta: + trait Params[+A, +B] +trait BetaInstances: + given schrodingerRandomBetaForDouble[F[_]: Monad]: Beta[Double][F] = ??? + +object all extends BetaInstances + +@main def Test = + import all.given + summon[Shrink[Beta.Params[Double, Double]]] \ No newline at end of file