Skip to content

Commit

Permalink
Another fix to the ranking logic
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Aug 5, 2024
1 parent e491c87 commit 5e14513
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 8 deletions.
16 changes: 8 additions & 8 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1481,8 +1481,8 @@ trait Implicits:
// 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)
compareAlternatives(newCand, ambi.alt1, disambiguate = true) > 0 &&
compareAlternatives(newCand, ambi.alt2, disambiguate = true) > 0)
}
}
case nil =>
Expand Down Expand Up @@ -1621,7 +1621,7 @@ trait Implicits:
throw ex

val sorted = sort(eligible)
val result = sorted match
val res = sorted match
case first :: rest =>
val firstIsImplicit = first.ref.symbol.is(Implicit)
if rest.exists(_.ref.symbol.is(Implicit) != firstIsImplicit) then
Expand All @@ -1638,11 +1638,11 @@ trait Implicits:

// Issue all priority change warnings that can affect the result
val shownWarnings = priorityChangeWarnings.toList.collect:
case (critical, msg) if result.found.exists(critical.contains(_)) =>
case (critical, msg) if res.found.exists(critical.contains(_)) =>
msg
result match
case result: SearchFailure =>
result.reason match
res match
case res: SearchFailure =>
res.reason match
case ambi: AmbiguousImplicits =>
// Make warnings part of error message because otherwise they are suppressed when
// the error is emitted.
Expand All @@ -1652,7 +1652,7 @@ trait Implicits:
for msg <- shownWarnings do
report.warning(msg, srcPos)

result
res
end searchImplicit

def isUnderSpecifiedArgument(tp: Type): Boolean =
Expand Down
20 changes: 20 additions & 0 deletions tests/warn/i15264.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- Warning: tests/warn/i15264.scala:48:26 ------------------------------------------------------------------------------
48 | val a = summon[A[Int]] // warn
| ^
| Given search preference for repro.A[Int] between alternatives
| (repro.exports.given_C_V : [V](using x$1: priority.Prio0): repro.C[V])
| and
| (repro.exports.given_A_V : [V](using x$1: priority.Prio2): repro.A[V])
| has changed.
| Previous choice : the first alternative
| New choice from Scala 3.7: the second alternative
-- Warning: tests/warn/i15264.scala:55:29 ------------------------------------------------------------------------------
55 | val a = summon[A[Q[Int]]] // warn
| ^
| Given search preference for repro.A[repro.Q[Int]] between alternatives
| (repro.qcontext.gcq : [V](using p0: priority.Prio0)(using c: repro.C[V]): repro.C[repro.Q[V]])
| and
| (repro.qcontext.gaq : [V](using p2: priority.Prio2)(using a: repro.A[V]): repro.A[repro.Q[V]])
| has changed.
| Previous choice : the first alternative
| New choice from Scala 3.7: the second alternative
55 changes: 55 additions & 0 deletions tests/warn/i15264.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import language.`3.7-migration`
object priority:
// lower number = higher priority
class Prio0 extends Prio1
object Prio0 { given Prio0() }

class Prio1 extends Prio2
object Prio1 { given Prio1() }

class Prio2
object Prio2 { given Prio2() }

object repro:
// analogous to cats Eq, Hash, Order:
class A[V]
class B[V] extends A[V]
class C[V] extends A[V]

class Q[V]

object context:
// prios work here, which is cool
given[V](using priority.Prio0): C[V] = new C[V]
given[V](using priority.Prio1): B[V] = new B[V]
given[V](using priority.Prio2): A[V] = new A[V]

object exports:
// so will these exports
export context.given

// if you import these don't import from 'context' above
object qcontext:
// base defs, like what you would get from cats
given ga: A[Int] = new B[Int] // added so that we don't get an ambiguity in test2
given gb: B[Int] = new B[Int]
given gc: C[Int] = new C[Int]

// these seem like they should work but don't
given gcq[V](using p0: priority.Prio0)(using c: C[V]): C[Q[V]] = new C[Q[V]]
given gbq[V](using p1: priority.Prio1)(using b: B[V]): B[Q[V]] = new B[Q[V]]
given gaq[V](using p2: priority.Prio2)(using a: A[V]): A[Q[V]] = new A[Q[V]]

object test1:
import repro.*
import repro.exports.given

// these will work
val a = summon[A[Int]] // warn


object test2:
import repro.*
import repro.qcontext.given

val a = summon[A[Q[Int]]] // warn

0 comments on commit 5e14513

Please sign in to comment.