@@ -1830,15 +1830,13 @@ trait Applications extends Compatibility {
1830
1830
isAsGood(alt1, tp1.instantiate(tparams.map(_.typeRef)), alt2, tp2)
1831
1831
}
1832
1832
case _ => // (3)
1833
- def compareValues (tp1 : Type , tp2 : Type )(using Context ) =
1834
- isAsGoodValueType(tp1, tp2, alt1.symbol.is(Implicit ), alt2.symbol.is(Implicit ))
1835
1833
tp2 match
1836
1834
case tp2 : MethodType => true // (3a)
1837
1835
case tp2 : PolyType if tp2.resultType.isInstanceOf [MethodType ] => true // (3a)
1838
1836
case tp2 : PolyType => // (3b)
1839
- explore(compareValues (tp1, instantiateWithTypeVars(tp2)))
1837
+ explore(isAsGoodValueType (tp1, instantiateWithTypeVars(tp2)))
1840
1838
case _ => // 3b)
1841
- compareValues (tp1, tp2)
1839
+ isAsGoodValueType (tp1, tp2)
1842
1840
}
1843
1841
1844
1842
/** Test whether value type `tp1` is as good as value type `tp2`.
@@ -1868,15 +1866,14 @@ trait Applications extends Compatibility {
1868
1866
* for overloading resolution (when `preferGeneral is false), and the opposite relation
1869
1867
* `U <: T` or `U convertible to `T` for implicit disambiguation between givens
1870
1868
* (when `preferGeneral` is true). For old-style implicit values, the 3.4 behavior is kept.
1871
- * If one of the alternatives is an implicit and the other is a given (or an extension), the implicit loses.
1872
1869
*
1873
1870
* - In Scala 3.5 and Scala 3.6-migration, we issue a warning if the result under
1874
1871
* Scala 3.6 differ wrt to the old behavior up to 3.5.
1875
1872
*
1876
1873
* Also and only for given resolution: If a compared type refers to a given or its module class, use
1877
1874
* the intersection of its parent classes instead.
1878
1875
*/
1879
- def isAsGoodValueType (tp1 : Type , tp2 : Type , alt1IsImplicit : Boolean , alt2IsImplicit : Boolean )(using Context ): Boolean =
1876
+ def isAsGoodValueType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
1880
1877
val oldResolution = ctx.mode.is(Mode .OldImplicitResolution )
1881
1878
if ! preferGeneral || Feature .migrateTo3 && oldResolution then
1882
1879
// Normal specificity test for overloading resolution (where `preferGeneral` is false)
@@ -1892,10 +1889,7 @@ trait Applications extends Compatibility {
1892
1889
val tp1p = prepare(tp1)
1893
1890
val tp2p = prepare(tp2)
1894
1891
1895
- if Feature .sourceVersion.isAtMost(SourceVersion .`3.4`)
1896
- || oldResolution
1897
- || alt1IsImplicit && alt2IsImplicit
1898
- then
1892
+ if Feature .sourceVersion.isAtMost(SourceVersion .`3.4`) || oldResolution then
1899
1893
// Intermediate rules: better means specialize, but map all type arguments downwards
1900
1894
// These are enabled for 3.0-3.5, and for all comparisons between old-style implicits,
1901
1895
// and in 3.5 and 3.6-migration when we compare with previous rules.
@@ -1909,9 +1903,8 @@ trait Applications extends Compatibility {
1909
1903
case _ => mapOver(t)
1910
1904
(flip(tp1p) relaxed_<:< flip(tp2p)) || viewExists(tp1, tp2)
1911
1905
else
1912
- // New rules: better means generalize, givens (and extensions) always beat implicits
1913
- if alt1IsImplicit != alt2IsImplicit then alt2IsImplicit
1914
- else (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
1906
+ // New rules: better means generalize
1907
+ (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
1915
1908
end isAsGoodValueType
1916
1909
1917
1910
/** Widen the result type of synthetic given methods from the implementation class to the
@@ -1970,8 +1963,9 @@ trait Applications extends Compatibility {
1970
1963
else if winsPrefix1 then 1
1971
1964
else - 1
1972
1965
1966
+ val ownerScore = compareOwner(alt1.symbol.maybeOwner, alt2.symbol.maybeOwner)
1967
+
1973
1968
def compareWithTypes (tp1 : Type , tp2 : Type ) =
1974
- val ownerScore = compareOwner(alt1.symbol.maybeOwner, alt2.symbol.maybeOwner)
1975
1969
val winsType1 = isAsGood(alt1, tp1, alt2, tp2)
1976
1970
val winsType2 = isAsGood(alt2, tp2, alt1, tp1)
1977
1971
@@ -1982,15 +1976,27 @@ trait Applications extends Compatibility {
1982
1976
// alternatives are the same after following ExprTypes, pick one of them
1983
1977
// (prefer the one that is not a method, but that's arbitrary).
1984
1978
if alt1.widenExpr =:= alt2 then - 1 else 1
1985
- else ownerScore match
1986
- case 1 => if winsType1 || ! winsType2 then 1 else 0
1987
- case - 1 => if winsType2 || ! winsType1 then - 1 else 0
1988
- case 0 =>
1989
- if winsType1 != winsType2 then if winsType1 then 1 else - 1
1990
- else if alt1.symbol == alt2.symbol then comparePrefixes
1991
- else 0
1979
+ else
1980
+ ownerScore match
1981
+ case 1 => if winsType1 || ! winsType2 then 1 else 0
1982
+ case - 1 => if winsType2 || ! winsType1 then - 1 else 0
1983
+ case 0 =>
1984
+ if winsType1 != winsType2 then if winsType1 then 1 else - 1
1985
+ else if alt1.symbol == alt2.symbol then comparePrefixes
1986
+ else 0
1992
1987
end compareWithTypes
1993
1988
1989
+ // For implicit resolution, take ownerscore as more significant than type resolution
1990
+ // Reason: People use owner hierarchies to explicitly prioritize, we should not
1991
+ // break that by changing implicit priority of types. On the other hand, we do
1992
+ // want to exhaust all other possibilities before using owner score as a tie breaker.
1993
+ // For instance, pos/scala-uri.scala depends on that.
1994
+ def drawOrOwner =
1995
+ if preferGeneral && ! ctx.mode.is(Mode .OldImplicitResolution ) then
1996
+ // println(i"disambi compare($alt1, $alt2)? $ownerScore")
1997
+ ownerScore
1998
+ else 0
1999
+
1994
2000
if alt1.symbol.is(ConstructorProxy ) && ! alt2.symbol.is(ConstructorProxy ) then - 1
1995
2001
else if alt2.symbol.is(ConstructorProxy ) && ! alt1.symbol.is(ConstructorProxy ) then 1
1996
2002
else
@@ -2000,11 +2006,12 @@ trait Applications extends Compatibility {
2000
2006
val strippedType2 = stripImplicit(fullType2)
2001
2007
2002
2008
val result = compareWithTypes(strippedType1, strippedType2)
2003
- if (result != 0 ) result
2004
- else if (strippedType1 eq fullType1)
2005
- if (strippedType2 eq fullType2) 0 // no implicits either side: its' a draw
2009
+ if result != 0 then result
2010
+ else if strippedType1 eq fullType1 then
2011
+ if strippedType2 eq fullType2
2012
+ then drawOrOwner // no implicits either side: its' a draw
2006
2013
else 1 // prefer 1st alternative with no implicits
2007
- else if ( strippedType2 eq fullType2) - 1 // prefer 2nd alternative with no implicits
2014
+ else if strippedType2 eq fullType2 then - 1 // prefer 2nd alternative with no implicits
2008
2015
else compareWithTypes(fullType1, fullType2) // continue by comparing implicits parameters
2009
2016
}
2010
2017
end compare
0 commit comments