Skip to content

Commit 7c4bd67

Browse files
committed
Compensate loss of transitivity
We only have transitivity between givens or between implicits. To cope with that - We tank first all implicits, giving a best implicit search result. - Then we rank all givens startign with the implicit result. If there is a given that is better than the best implicit, the best given will be chosen. Otherwise we will stick with the best implicit.
1 parent 35b5f7c commit 7c4bd67

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

Diff for: compiler/src/dotty/tools/dotc/typer/Implicits.scala

+15-3
Original file line numberDiff line numberDiff line change
@@ -1381,8 +1381,6 @@ trait Implicits:
13811381
def disambiguate(alt1: SearchResult, alt2: SearchSuccess) = alt1 match
13821382
case alt1: SearchSuccess =>
13831383
var diff = compareAlternatives(alt1, alt2, disambiguate = true)
1384-
assert(diff <= 0 || isWarnPriorityChangeVersion(Feature.sourceVersion))
1385-
// diff > 0 candidates should already have been eliminated in `rank`
13861384
if diff == 0 && alt1.ref =:= alt2.ref then
13871385
diff = 1 // See i12951 for a test where this happens
13881386
else if diff == 0 && alt2.isExtension then
@@ -1622,7 +1620,21 @@ trait Implicits:
16221620
validateOrdering(ord)
16231621
throw ex
16241622

1625-
val result = rank(sort(eligible), NoMatchingImplicitsFailure, Nil)
1623+
val sorted = sort(eligible)
1624+
val result = sorted match
1625+
case first :: rest =>
1626+
val firstIsImplicit = first.ref.symbol.is(Implicit)
1627+
if rest.exists(_.ref.symbol.is(Implicit) != firstIsImplicit) then
1628+
// Mixture of implicits and givens
1629+
// Rank implicits first, then, if there is a given that it better than the best implicit(s)
1630+
// switch over to givens.
1631+
val (sortedImplicits, sortedGivens) = sorted.partition(_.ref.symbol.is(Implicit))
1632+
val implicitResult = rank(sortedImplicits, NoMatchingImplicitsFailure, Nil)
1633+
rank(sortedGivens, implicitResult, Nil)
1634+
else
1635+
rank(sorted, NoMatchingImplicitsFailure, Nil)
1636+
case _ =>
1637+
NoMatchingImplicitsFailure
16261638

16271639
// Issue all priority change warnings that can affect the result
16281640
val shownWarnings = priorityChangeWarnings.toList.collect:

Diff for: tests/pos/given-owner-disambiguate.scala

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class General
2+
class Specific extends General
3+
4+
class LowPriority:
5+
given a:General()
6+
7+
object NormalPriority extends LowPriority:
8+
given b:Specific()
9+
10+
def run =
11+
import NormalPriority.given
12+
val x = summon[General]
13+
val _: Specific = x // <- b was picked

0 commit comments

Comments
 (0)