@@ -1762,6 +1762,17 @@ trait Applications extends Compatibility {
1762
1762
else if sym2.is(Module ) then compareOwner(sym1, cls2)
1763
1763
else 0
1764
1764
1765
+ enum CompareScheme :
1766
+ case Old // Normal specificity test for overloading resolution (where `preferGeneral` is false)
1767
+ // and in mode Scala3-migration when we compare with the old Scala 2 rules.
1768
+
1769
+ case Intermediate // Intermediate rules: better means specialize, but map all type arguments downwards
1770
+ // These are enabled for 3.0-3.5, or if OldImplicitResolution
1771
+ // is specified, and also for all comparisons between old-style implicits,
1772
+
1773
+ case New // New rules: better means generalize, givens (and extensions) always beat implicits
1774
+ end CompareScheme
1775
+
1765
1776
/** Compare two alternatives of an overloaded call or an implicit search.
1766
1777
*
1767
1778
* @param alt1, alt2 Non-overloaded references indicating the two choices
@@ -1788,6 +1799,15 @@ trait Applications extends Compatibility {
1788
1799
*/
1789
1800
def compare (alt1 : TermRef , alt2 : TermRef , preferGeneral : Boolean = false )(using Context ): Int = trace(i " compare( $alt1, $alt2) " , overload) {
1790
1801
record(" resolveOverloaded.compare" )
1802
+ val scheme =
1803
+ val oldResolution = ctx.mode.is(Mode .OldImplicitResolution )
1804
+ if ! preferGeneral || Feature .migrateTo3 && oldResolution then
1805
+ CompareScheme .Old
1806
+ else if Feature .sourceVersion.isAtMost(SourceVersion .`3.5`)
1807
+ || oldResolution
1808
+ || alt1.symbol.is(Implicit ) && alt2.symbol.is(Implicit )
1809
+ then CompareScheme .Intermediate
1810
+ else CompareScheme .New
1791
1811
1792
1812
/** Is alternative `alt1` with type `tp1` as good as alternative
1793
1813
* `alt2` with type `tp2` ?
@@ -1830,15 +1850,15 @@ trait Applications extends Compatibility {
1830
1850
isAsGood(alt1, tp1.instantiate(tparams.map(_.typeRef)), alt2, tp2)
1831
1851
}
1832
1852
case _ => // (3)
1833
- def compareValues (tp1 : Type , tp2 : Type )(using Context ) =
1834
- isAsGoodValueType(tp1, tp2, alt1.symbol.is(Implicit ), alt2.symbol.is( Implicit ) )
1853
+ def compareValues (tp2 : Type )(using Context ) =
1854
+ isAsGoodValueType(tp1, tp2, alt1.symbol.is(Implicit ))
1835
1855
tp2 match
1836
1856
case tp2 : MethodType => true // (3a)
1837
1857
case tp2 : PolyType if tp2.resultType.isInstanceOf [MethodType ] => true // (3a)
1838
1858
case tp2 : PolyType => // (3b)
1839
- explore(compareValues(tp1, instantiateWithTypeVars(tp2)))
1859
+ explore(compareValues(instantiateWithTypeVars(tp2)))
1840
1860
case _ => // 3b)
1841
- compareValues(tp1, tp2)
1861
+ compareValues(tp2)
1842
1862
}
1843
1863
1844
1864
/** Test whether value type `tp1` is as good as value type `tp2`.
@@ -1849,7 +1869,7 @@ trait Applications extends Compatibility {
1849
1869
* available in 3.0-migration if mode `Mode.OldImplicitResolution` is turned on as well.
1850
1870
* It is used to highlight differences between Scala 2 and 3 behavior.
1851
1871
*
1852
- * - In Scala 3.0-3.5 , the behavior is as follows: `T <:p U` iff there is an implicit conversion
1872
+ * - In Scala 3.0-3.6 , the behavior is as follows: `T <:p U` iff there is an implicit conversion
1853
1873
* from `T` to `U`, or
1854
1874
*
1855
1875
* flip(T) <: flip(U)
@@ -1864,21 +1884,20 @@ trait Applications extends Compatibility {
1864
1884
* of parameters are not affected. So `T <: U` would imply `Set[Cmp[U]] <:p Set[Cmp[T]]`,
1865
1885
* as usual, because `Set` is non-variant.
1866
1886
*
1867
- * - From Scala 3.6 , `T <:p U` means `T <: U` or `T` convertible to `U`
1887
+ * - From Scala 3.7 , `T <:p U` means `T <: U` or `T` convertible to `U`
1868
1888
* for overloading resolution (when `preferGeneral is false), and the opposite relation
1869
1889
* `U <: T` or `U convertible to `T` for implicit disambiguation between givens
1870
- * (when `preferGeneral` is true). For old-style implicit values, the 3.4 behavior is kept.
1890
+ * (when `preferGeneral` is true). For old-style implicit values, the 3.5 behavior is kept.
1871
1891
* If one of the alternatives is an implicit and the other is a given (or an extension), the implicit loses.
1872
1892
*
1873
- * - In Scala 3.5 and Scala 3.6 -migration, we issue a warning if the result under
1874
- * Scala 3.6 differ wrt to the old behavior up to 3.5 .
1893
+ * - In Scala 3.6 and Scala 3.7 -migration, we issue a warning if the result under
1894
+ * Scala 3.7 differs wrt to the old behavior up to 3.6 .
1875
1895
*
1876
1896
* Also and only for given resolution: If a compared type refers to a given or its module class, use
1877
1897
* the intersection of its parent classes instead.
1878
1898
*/
1879
- def isAsGoodValueType (tp1 : Type , tp2 : Type , alt1IsImplicit : Boolean , alt2IsImplicit : Boolean )(using Context ): Boolean =
1880
- val oldResolution = ctx.mode.is(Mode .OldImplicitResolution )
1881
- if ! preferGeneral || Feature .migrateTo3 && oldResolution then
1899
+ def isAsGoodValueType (tp1 : Type , tp2 : Type , alt1IsImplicit : Boolean )(using Context ): Boolean =
1900
+ if scheme == CompareScheme .Old then
1882
1901
// Normal specificity test for overloading resolution (where `preferGeneral` is false)
1883
1902
// and in mode Scala3-migration when we compare with the old Scala 2 rules.
1884
1903
isCompatible(tp1, tp2)
@@ -1892,13 +1911,7 @@ trait Applications extends Compatibility {
1892
1911
val tp1p = prepare(tp1)
1893
1912
val tp2p = prepare(tp2)
1894
1913
1895
- if Feature .sourceVersion.isAtMost(SourceVersion .`3.4`)
1896
- || oldResolution
1897
- || alt1IsImplicit && alt2IsImplicit
1898
- then
1899
- // Intermediate rules: better means specialize, but map all type arguments downwards
1900
- // These are enabled for 3.0-3.5, and for all comparisons between old-style implicits,
1901
- // and in 3.5 and 3.6-migration when we compare with previous rules.
1914
+ if scheme == CompareScheme .Intermediate || alt1IsImplicit then
1902
1915
val flip = new TypeMap :
1903
1916
def apply (t : Type ) = t match
1904
1917
case t @ AppliedType (tycon, args) =>
@@ -1909,9 +1922,7 @@ trait Applications extends Compatibility {
1909
1922
case _ => mapOver(t)
1910
1923
(flip(tp1p) relaxed_<:< flip(tp2p)) || viewExists(tp1, tp2)
1911
1924
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)
1925
+ (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
1915
1926
end isAsGoodValueType
1916
1927
1917
1928
/** Widen the result type of synthetic given methods from the implementation class to the
@@ -1982,13 +1993,19 @@ trait Applications extends Compatibility {
1982
1993
// alternatives are the same after following ExprTypes, pick one of them
1983
1994
// (prefer the one that is not a method, but that's arbitrary).
1984
1995
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
1996
+ else
1997
+ // For new implicit resolution, take ownerscore as more significant than type resolution
1998
+ // Reason: People use owner hierarchies to explicitly prioritize, we should not
1999
+ // break that by changing implicit priority of types.
2000
+ def drawOrOwner =
2001
+ if scheme == CompareScheme .New then ownerScore else 0
2002
+ ownerScore match
2003
+ case 1 => if winsType1 || ! winsType2 then 1 else drawOrOwner
2004
+ case - 1 => if winsType2 || ! winsType1 then - 1 else drawOrOwner
2005
+ case 0 =>
2006
+ if winsType1 != winsType2 then if winsType1 then 1 else - 1
2007
+ else if alt1.symbol == alt2.symbol then comparePrefixes
2008
+ else 0
1992
2009
end compareWithTypes
1993
2010
1994
2011
if alt1.symbol.is(ConstructorProxy ) && ! alt2.symbol.is(ConstructorProxy ) then - 1
0 commit comments