@@ -1748,6 +1748,17 @@ trait Applications extends Compatibility {
1748
1748
else if sym2.is(Module ) then compareOwner(sym1, cls2)
1749
1749
else 0
1750
1750
1751
+ enum CompareScheme :
1752
+ case Old // Normal specificity test for overloading resolution (where `preferGeneral` is false)
1753
+ // and in mode Scala3-migration when we compare with the old Scala 2 rules.
1754
+
1755
+ case Intermediate // Intermediate rules: better means specialize, but map all type arguments downwards
1756
+ // These are enabled for 3.0-3.5, or if OldImplicitResolution
1757
+ // is specified, and also for all comparisons between old-style implicits,
1758
+
1759
+ case New // New rules: better means generalize, givens (and extensions) always beat implicits
1760
+ end CompareScheme
1761
+
1751
1762
/** Compare two alternatives of an overloaded call or an implicit search.
1752
1763
*
1753
1764
* @param alt1, alt2 Non-overloaded references indicating the two choices
@@ -1774,6 +1785,15 @@ trait Applications extends Compatibility {
1774
1785
*/
1775
1786
def compare (alt1 : TermRef , alt2 : TermRef , preferGeneral : Boolean = false )(using Context ): Int = trace(i " compare( $alt1, $alt2) " , overload) {
1776
1787
record(" resolveOverloaded.compare" )
1788
+ val scheme =
1789
+ val oldResolution = ctx.mode.is(Mode .OldImplicitResolution )
1790
+ if ! preferGeneral || Feature .migrateTo3 && oldResolution then
1791
+ CompareScheme .Old
1792
+ else if Feature .sourceVersion.isAtMost(SourceVersion .`3.5`)
1793
+ || oldResolution
1794
+ || alt1.symbol.is(Implicit ) && alt2.symbol.is(Implicit )
1795
+ then CompareScheme .Intermediate
1796
+ else CompareScheme .New
1777
1797
1778
1798
/** Is alternative `alt1` with type `tp1` as good as alternative
1779
1799
* `alt2` with type `tp2` ?
@@ -1816,17 +1836,15 @@ trait Applications extends Compatibility {
1816
1836
isAsGood(alt1, tp1.instantiate(tparams.map(_.typeRef)), alt2, tp2)
1817
1837
}
1818
1838
case _ => // (3)
1819
- def isGiven (alt : TermRef ) =
1820
- alt1.symbol.is(Given ) && alt.symbol != defn.NotGivenClass
1821
- def compareValues (tp1 : Type , tp2 : Type )(using Context ) =
1822
- isAsGoodValueType(tp1, tp2, isGiven(alt1), isGiven(alt2))
1839
+ def compareValues (tp2 : Type )(using Context ) =
1840
+ isAsGoodValueType(tp1, tp2, alt1.symbol.is(Implicit ))
1823
1841
tp2 match
1824
1842
case tp2 : MethodType => true // (3a)
1825
1843
case tp2 : PolyType if tp2.resultType.isInstanceOf [MethodType ] => true // (3a)
1826
1844
case tp2 : PolyType => // (3b)
1827
- explore(compareValues(tp1, instantiateWithTypeVars(tp2)))
1845
+ explore(compareValues(instantiateWithTypeVars(tp2)))
1828
1846
case _ => // 3b)
1829
- compareValues(tp1, tp2)
1847
+ compareValues(tp2)
1830
1848
}
1831
1849
1832
1850
/** Test whether value type `tp1` is as good as value type `tp2`.
@@ -1837,7 +1855,7 @@ trait Applications extends Compatibility {
1837
1855
* available in 3.0-migration if mode `Mode.OldImplicitResolution` is turned on as well.
1838
1856
* It is used to highlight differences between Scala 2 and 3 behavior.
1839
1857
*
1840
- * - In Scala 3.0-3.5 , the behavior is as follows: `T <:p U` iff there is an impliit conversion
1858
+ * - In Scala 3.0-3.6 , the behavior is as follows: `T <:p U` iff there is an implicit conversion
1841
1859
* from `T` to `U`, or
1842
1860
*
1843
1861
* flip(T) <: flip(U)
@@ -1852,21 +1870,20 @@ trait Applications extends Compatibility {
1852
1870
* of parameters are not affected. So `T <: U` would imply `Set[Cmp[U]] <:p Set[Cmp[T]]`,
1853
1871
* as usual, because `Set` is non-variant.
1854
1872
*
1855
- * - From Scala 3.6 , `T <:p U` means `T <: U` or `T` convertible to `U`
1873
+ * - From Scala 3.7 , `T <:p U` means `T <: U` or `T` convertible to `U`
1856
1874
* for overloading resolution (when `preferGeneral is false), and the opposite relation
1857
1875
* `U <: T` or `U convertible to `T` for implicit disambiguation between givens
1858
- * (when `preferGeneral` is true). For old-style implicit values, the 3.4 behavior is kept.
1859
- * If one of the alternatives is a given and the other is an implicit , the given wins .
1876
+ * (when `preferGeneral` is true). For old-style implicit values, the 3.5 behavior is kept.
1877
+ * If one of the alternatives is an implicit and the other is a given (or an extension) , the implicit loses .
1860
1878
*
1861
- * - In Scala 3.5 and Scala 3.6 -migration, we issue a warning if the result under
1862
- * Scala 3.6 differ wrt to the old behavior up to 3.5 .
1879
+ * - In Scala 3.6 and Scala 3.7 -migration, we issue a warning if the result under
1880
+ * Scala 3.7 differs wrt to the old behavior up to 3.6 .
1863
1881
*
1864
1882
* Also and only for given resolution: If a compared type refers to a given or its module class, use
1865
1883
* the intersection of its parent classes instead.
1866
1884
*/
1867
- def isAsGoodValueType (tp1 : Type , tp2 : Type , alt1isGiven : Boolean , alt2isGiven : Boolean )(using Context ): Boolean =
1868
- val oldResolution = ctx.mode.is(Mode .OldImplicitResolution )
1869
- if ! preferGeneral || Feature .migrateTo3 && oldResolution then
1885
+ def isAsGoodValueType (tp1 : Type , tp2 : Type , alt1IsImplicit : Boolean )(using Context ): Boolean =
1886
+ if scheme == CompareScheme .Old then
1870
1887
// Normal specificity test for overloading resolution (where `preferGeneral` is false)
1871
1888
// and in mode Scala3-migration when we compare with the old Scala 2 rules.
1872
1889
isCompatible(tp1, tp2)
@@ -1880,13 +1897,7 @@ trait Applications extends Compatibility {
1880
1897
val tp1p = prepare(tp1)
1881
1898
val tp2p = prepare(tp2)
1882
1899
1883
- if Feature .sourceVersion.isAtMost(SourceVersion .`3.4`)
1884
- || oldResolution
1885
- || ! alt1isGiven && ! alt2isGiven
1886
- then
1887
- // Intermediate rules: better means specialize, but map all type arguments downwards
1888
- // These are enabled for 3.0-3.5, and for all comparisons between old-style implicits,
1889
- // and in 3.5 and 3.6-migration when we compare with previous rules.
1900
+ if scheme == CompareScheme .Intermediate || alt1IsImplicit then
1890
1901
val flip = new TypeMap :
1891
1902
def apply (t : Type ) = t match
1892
1903
case t @ AppliedType (tycon, args) =>
@@ -1897,9 +1908,7 @@ trait Applications extends Compatibility {
1897
1908
case _ => mapOver(t)
1898
1909
(flip(tp1p) relaxed_<:< flip(tp2p)) || viewExists(tp1, tp2)
1899
1910
else
1900
- // New rules: better means generalize, givens always beat implicits
1901
- if alt1isGiven != alt2isGiven then alt1isGiven
1902
- else (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
1911
+ (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
1903
1912
end isAsGoodValueType
1904
1913
1905
1914
/** Widen the result type of synthetic given methods from the implementation class to the
@@ -1970,13 +1979,19 @@ trait Applications extends Compatibility {
1970
1979
// alternatives are the same after following ExprTypes, pick one of them
1971
1980
// (prefer the one that is not a method, but that's arbitrary).
1972
1981
if alt1.widenExpr =:= alt2 then - 1 else 1
1973
- else ownerScore match
1974
- case 1 => if winsType1 || ! winsType2 then 1 else 0
1975
- case - 1 => if winsType2 || ! winsType1 then - 1 else 0
1976
- case 0 =>
1977
- if winsType1 != winsType2 then if winsType1 then 1 else - 1
1978
- else if alt1.symbol == alt2.symbol then comparePrefixes
1979
- else 0
1982
+ else
1983
+ // For new implicit resolution, take ownerscore as more significant than type resolution
1984
+ // Reason: People use owner hierarchies to explicitly prioritize, we should not
1985
+ // break that by changing implicit priority of types.
1986
+ def drawOrOwner =
1987
+ if scheme == CompareScheme .New then ownerScore else 0
1988
+ ownerScore match
1989
+ case 1 => if winsType1 || ! winsType2 then 1 else drawOrOwner
1990
+ case - 1 => if winsType2 || ! winsType1 then - 1 else drawOrOwner
1991
+ case 0 =>
1992
+ if winsType1 != winsType2 then if winsType1 then 1 else - 1
1993
+ else if alt1.symbol == alt2.symbol then comparePrefixes
1994
+ else 0
1980
1995
end compareWithTypes
1981
1996
1982
1997
if alt1.symbol.is(ConstructorProxy ) && ! alt2.symbol.is(ConstructorProxy ) then - 1
0 commit comments