Skip to content

Commit 205272c

Browse files
committed
Refine overloading and implicit disambiguation
We sometimes have two alternatives a.m and b.m with the same symbol but different prefixes. Previously these would always be ambiguous. We now try to disambiguate this so that the alternative with the more specific prefix wins. To determine this, we widen prefixes also going from module classes to their parents and then compare the resulting types. This might fix a problem in ScalaTest that popped up after #20054.
1 parent c8c3bde commit 205272c

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

compiler/src/dotty/tools/dotc/typer/Applications.scala

+31-1
Original file line numberDiff line numberDiff line change
@@ -1807,8 +1807,38 @@ trait Applications extends Compatibility {
18071807
else tp
18081808
}
18091809

1810+
def widenPrefix(alt: TermRef): Type = alt.prefix.widen match
1811+
case pre: (TypeRef | ThisType) if pre.typeSymbol.is(Module) =>
1812+
pre.parents.reduceLeft(TypeComparer.andType(_, _))
1813+
case wpre => wpre
1814+
1815+
/** If two alternatives have the same symbol, we pick the one with the most
1816+
* specific prefix. To determine that, we widen the prefix types and also
1817+
* widen module classes to the intersection of their parent classes. Then
1818+
* if one of the resulting types is a more specific value type than the other,
1819+
* it wins. Example:
1820+
*
1821+
* trait A { given M = ... }
1822+
* trait B extends A
1823+
* object a extends A
1824+
* object b extends B
1825+
*
1826+
* In this case `b.M` would be regarded as more specific than `a.M`.
1827+
*/
1828+
def comparePrefixes(pre1: Type, pre2: Type) =
1829+
val winsPrefix1 = isAsSpecificValueType(pre1, pre2)
1830+
val winsPrefix2 = isAsSpecificValueType(pre2, pre1)
1831+
if winsPrefix1 == winsPrefix2 then 0
1832+
else if winsPrefix1 then 1
1833+
else -1
1834+
18101835
def compareWithTypes(tp1: Type, tp2: Type) = {
1811-
val ownerScore = compareOwner(alt1.symbol.maybeOwner, alt2.symbol.maybeOwner)
1836+
val ownerScore =
1837+
val sym1 = alt1.symbol
1838+
val sym2 = alt2.symbol
1839+
if sym1 == sym2 then comparePrefixes(widenPrefix(alt1), widenPrefix(alt2))
1840+
else compareOwner(sym1.maybeOwner, sym2.maybeOwner)
1841+
18121842
def winsType1 = isAsSpecific(alt1, tp1, alt2, tp2)
18131843
def winsType2 = isAsSpecific(alt2, tp2, alt1, tp1)
18141844

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class I[X]
2+
3+
trait A:
4+
given I[B] = ???
5+
object A extends A
6+
7+
trait B extends A
8+
object B extends B
9+
10+
//import B.given, A.given
11+
12+
def Test = summon[I[B]]
13+
14+

0 commit comments

Comments
 (0)