Skip to content

Commit

Permalink
Do prefix comparison only as a final tie breaker
Browse files Browse the repository at this point in the history
The alternatives with the same symbol could have nevertheless different types. We first want
to disambiguate based on these types before we turn to prefixes as a final tie breaker,
including after trying comparison with implicit parameters.
  • Loading branch information
EugeneFlesselle committed Apr 8, 2024
1 parent 2e640c2 commit 381285b
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 21 deletions.
33 changes: 15 additions & 18 deletions compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1831,22 +1831,20 @@ trait Applications extends Compatibility {
*
* In this case `b.M` would be regarded as more specific than `a.M`.
*/
def comparePrefixes(pre1: Type, pre2: Type) =
def comparePrefixes =
val pre1 = widenPrefix(alt1)
val pre2 = widenPrefix(alt2)
val winsPrefix1 = isAsSpecificValueType(pre1, pre2)
val winsPrefix2 = isAsSpecificValueType(pre2, pre1)
if winsPrefix1 == winsPrefix2 then 0
else if winsPrefix1 then 1
else -1

def compareWithTypes(tp1: Type, tp2: Type) = {
val ownerScore =
val sym1 = alt1.symbol
val sym2 = alt2.symbol
if sym1 == sym2 then comparePrefixes(widenPrefix(alt1), widenPrefix(alt2))
else compareOwner(sym1.maybeOwner, sym2.maybeOwner)
def compareWithTypes(tp1: Type, tp2: Type) =
val ownerScore = compareOwner(alt1.symbol.maybeOwner, alt2.symbol.maybeOwner)

def winsType1 = isAsSpecific(alt1, tp1, alt2, tp2)
def winsType2 = isAsSpecific(alt2, tp2, alt1, tp1)
val winsType1 = isAsSpecific(alt1, tp1, alt2, tp2)
val winsType2 = isAsSpecific(alt2, tp2, alt1, tp1)

overload.println(i"compare($alt1, $alt2)? $tp1 $tp2 $ownerScore $winsType1 $winsType2")
if winsType1 && winsType2
Expand All @@ -1855,15 +1853,14 @@ trait Applications extends Compatibility {
// alternatives are the same after following ExprTypes, pick one of them
// (prefer the one that is not a method, but that's arbitrary).
if alt1.widenExpr =:= alt2 then -1 else 1
else if ownerScore == 1 then
if winsType1 || !winsType2 then 1 else 0
else if ownerScore == -1 then
if winsType2 || !winsType1 then -1 else 0
else if winsType1 then
if winsType2 then 0 else 1
else
if winsType2 then -1 else 0
}
else ownerScore match
case 1 => if winsType1 || !winsType2 then 1 else 0
case -1 => if winsType2 || !winsType1 then -1 else 0
case 0 =>
if winsType1 != winsType2 then if winsType1 then 1 else -1
else if alt1.symbol == alt2.symbol then comparePrefixes
else 0
end compareWithTypes

if alt1.symbol.is(ConstructorProxy) && !alt2.symbol.is(ConstructorProxy) then -1
else if alt2.symbol.is(ConstructorProxy) && !alt1.symbol.is(ConstructorProxy) then 1
Expand Down
9 changes: 6 additions & 3 deletions tests/pos/implicit-prefix-disambiguation.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@

class I[X]
class J[X]

trait A:
given I[B] = ???
given (using I[B]): J[B] = ???
object A extends A

trait B extends A
object B extends B

//import B.given, A.given

def Test = summon[I[B]]


def Test =
summon[I[B]]
summon[J[B]]

0 comments on commit 381285b

Please sign in to comment.