@@ -1733,8 +1733,6 @@ trait Applications extends Compatibility {
1733
1733
def compare (alt1 : TermRef , alt2 : TermRef , preferGeneral : Boolean = false )(using Context ): Int = trace(i " compare( $alt1, $alt2) " , overload) {
1734
1734
record(" resolveOverloaded.compare" )
1735
1735
1736
- val compareGivens = alt1.symbol.is(Given ) && alt2.symbol.is(Given )
1737
-
1738
1736
/** Is alternative `alt1` with type `tp1` as good as alternative
1739
1737
* `alt2` with type `tp2` ?
1740
1738
*
@@ -1749,7 +1747,7 @@ trait Applications extends Compatibility {
1749
1747
* from below by Li and from above by Ui.
1750
1748
* 3. A member of any other type `tp1` is:
1751
1749
* a. always as good as a method or a polymorphic method.
1752
- * b. as good as a member of any other type `tp2` is `asGoodValueType(tp1, tp2) = true`
1750
+ * b. as good as a member of any other type `tp2` if `asGoodValueType(tp1, tp2) = true`
1753
1751
*/
1754
1752
def isAsGood (alt1 : TermRef , tp1 : Type , alt2 : TermRef , tp2 : Type ): Boolean = trace(i " isAsSpecific $tp1 $tp2" , overload) {
1755
1753
tp1 match
@@ -1776,13 +1774,17 @@ trait Applications extends Compatibility {
1776
1774
isAsGood(alt1, tp1.instantiate(tparams.map(_.typeRef)), alt2, tp2)
1777
1775
}
1778
1776
case _ => // (3)
1777
+ def isGiven (alt : TermRef ) =
1778
+ alt1.symbol.is(Given ) && alt.symbol != defn.NotGivenClass
1779
+ def compareValues (tp1 : Type , tp2 : Type )(using Context ) =
1780
+ isAsGoodValueType(tp1, tp2, isGiven(alt1), isGiven(alt2))
1779
1781
tp2 match
1780
1782
case tp2 : MethodType => true // (3a)
1781
1783
case tp2 : PolyType if tp2.resultType.isInstanceOf [MethodType ] => true // (3a)
1782
1784
case tp2 : PolyType => // (3b)
1783
- explore(isAsGoodValueType (tp1, instantiateWithTypeVars(tp2)))
1785
+ explore(compareValues (tp1, instantiateWithTypeVars(tp2)))
1784
1786
case _ => // 3b)
1785
- isAsGoodValueType (tp1, tp2)
1787
+ compareValues (tp1, tp2)
1786
1788
}
1787
1789
1788
1790
/** Test whether value type `tp1` is as good as value type `tp2`.
@@ -1812,6 +1814,7 @@ trait Applications extends Compatibility {
1812
1814
* for overloading resolution (when `preferGeneral is false), and the opposite relation
1813
1815
* `U <: T` or `U convertible to `T` for implicit disambiguation between givens
1814
1816
* (when `preferGeneral` is true). For old-style implicit values, the 3.4 behavior is kept.
1817
+ * If one of the alternatives is a given and the other is an implicit, the given wins.
1815
1818
*
1816
1819
* - In Scala 3.5-migration, use the 3.5 scheme normally, and the 3.4 scheme if
1817
1820
* `Mode.OldImplicitResolution` is on. This is used to highlight differences in the
@@ -1820,7 +1823,7 @@ trait Applications extends Compatibility {
1820
1823
* Also and only for given resolution: If a compared type refers to a given or its module class, use
1821
1824
* the intersection of its parent classes instead.
1822
1825
*/
1823
- def isAsGoodValueType (tp1 : Type , tp2 : Type )(using Context ) =
1826
+ def isAsGoodValueType (tp1 : Type , tp2 : Type , alt1isGiven : Boolean , alt2isGiven : Boolean )(using Context ): Boolean =
1824
1827
val oldResolution = ctx.mode.is(Mode .OldImplicitResolution )
1825
1828
if ! preferGeneral || Feature .migrateTo3 && oldResolution then
1826
1829
// Normal specificity test for overloading resolution (where `preferGeneral` is false)
@@ -1838,7 +1841,7 @@ trait Applications extends Compatibility {
1838
1841
1839
1842
if Feature .sourceVersion.isAtMost(SourceVersion .`3.4`)
1840
1843
|| oldResolution
1841
- || ! compareGivens
1844
+ || ! alt1isGiven && ! alt2isGiven
1842
1845
then
1843
1846
// Intermediate rules: better means specialize, but map all type arguments downwards
1844
1847
// These are enabled for 3.0-3.4, and for all comparisons between old-style implicits,
@@ -1853,8 +1856,9 @@ trait Applications extends Compatibility {
1853
1856
case _ => mapOver(t)
1854
1857
(flip(tp1p) relaxed_<:< flip(tp2p)) || viewExists(tp1, tp2)
1855
1858
else
1856
- // New rules: better means generalize
1857
- (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
1859
+ // New rules: better means generalize, givens always beat implicits
1860
+ if alt1isGiven != alt2isGiven then alt1isGiven
1861
+ else (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
1858
1862
end isAsGoodValueType
1859
1863
1860
1864
/** Widen the result type of synthetic given methods from the implementation class to the
@@ -1907,8 +1911,8 @@ trait Applications extends Compatibility {
1907
1911
def comparePrefixes =
1908
1912
val pre1 = widenPrefix(alt1)
1909
1913
val pre2 = widenPrefix(alt2)
1910
- val winsPrefix1 = isAsGoodValueType (pre1, pre2)
1911
- val winsPrefix2 = isAsGoodValueType (pre2, pre1)
1914
+ val winsPrefix1 = isCompatible (pre1, pre2)
1915
+ val winsPrefix2 = isCompatible (pre2, pre1)
1912
1916
if winsPrefix1 == winsPrefix2 then 0
1913
1917
else if winsPrefix1 then 1
1914
1918
else - 1
0 commit comments