@@ -1748,6 +1748,17 @@ trait Applications extends Compatibility {
17481748 else if sym2.is(Module ) then compareOwner(sym1, cls2)
17491749 else 0
17501750
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.4, 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+
17511762 /** Compare two alternatives of an overloaded call or an implicit search.
17521763 *
17531764 * @param alt1, alt2 Non-overloaded references indicating the two choices
@@ -1774,6 +1785,15 @@ trait Applications extends Compatibility {
17741785 */
17751786 def compare (alt1 : TermRef , alt2 : TermRef , preferGeneral : Boolean = false )(using Context ): Int = trace(i " compare( $alt1, $alt2) " , overload) {
17761787 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.4`)
1793+ || oldResolution
1794+ || alt1.symbol.is(Implicit ) && alt2.symbol.is(Implicit )
1795+ then CompareScheme .Intermediate
1796+ else CompareScheme .New
17771797
17781798 /** Is alternative `alt1` with type `tp1` as good as alternative
17791799 * `alt2` with type `tp2` ?
@@ -1816,15 +1836,15 @@ trait Applications extends Compatibility {
18161836 isAsGood(alt1, tp1.instantiate(tparams.map(_.typeRef)), alt2, tp2)
18171837 }
18181838 case _ => // (3)
1819- def compareValues (tp1 : Type , tp2 : Type )(using Context ) =
1820- isAsGoodValueType(tp1, tp2, alt1.symbol.is(Implicit ), alt2.symbol.is( Implicit ) )
1839+ def compareValues (tp2 : Type )(using Context ) =
1840+ isAsGoodValueType(tp1, tp2, alt1.symbol.is(Implicit ))
18211841 tp2 match
18221842 case tp2 : MethodType => true // (3a)
18231843 case tp2 : PolyType if tp2.resultType.isInstanceOf [MethodType ] => true // (3a)
18241844 case tp2 : PolyType => // (3b)
1825- explore(compareValues(tp1, instantiateWithTypeVars(tp2)))
1845+ explore(compareValues(instantiateWithTypeVars(tp2)))
18261846 case _ => // 3b)
1827- compareValues(tp1, tp2)
1847+ compareValues(tp2)
18281848 }
18291849
18301850 /** Test whether value type `tp1` is as good as value type `tp2`.
@@ -1862,9 +1882,8 @@ trait Applications extends Compatibility {
18621882 * Also and only for given resolution: If a compared type refers to a given or its module class, use
18631883 * the intersection of its parent classes instead.
18641884 */
1865- def isAsGoodValueType (tp1 : Type , tp2 : Type , alt1IsImplicit : Boolean , alt2IsImplicit : Boolean )(using Context ): Boolean =
1866- val oldResolution = ctx.mode.is(Mode .OldImplicitResolution )
1867- if ! preferGeneral || Feature .migrateTo3 && oldResolution then
1885+ def isAsGoodValueType (tp1 : Type , tp2 : Type , alt1IsImplicit : Boolean )(using Context ): Boolean =
1886+ if scheme == CompareScheme .Old then
18681887 // Normal specificity test for overloading resolution (where `preferGeneral` is false)
18691888 // and in mode Scala3-migration when we compare with the old Scala 2 rules.
18701889 isCompatible(tp1, tp2)
@@ -1878,13 +1897,7 @@ trait Applications extends Compatibility {
18781897 val tp1p = prepare(tp1)
18791898 val tp2p = prepare(tp2)
18801899
1881- if Feature .sourceVersion.isAtMost(SourceVersion .`3.4`)
1882- || oldResolution
1883- || alt1IsImplicit && alt2IsImplicit
1884- then
1885- // Intermediate rules: better means specialize, but map all type arguments downwards
1886- // These are enabled for 3.0-3.5, and for all comparisons between old-style implicits,
1887- // and in 3.5 and 3.6-migration when we compare with previous rules.
1900+ if scheme == CompareScheme .Intermediate || alt1IsImplicit then
18881901 val flip = new TypeMap :
18891902 def apply (t : Type ) = t match
18901903 case t @ AppliedType (tycon, args) =>
@@ -1895,9 +1908,7 @@ trait Applications extends Compatibility {
18951908 case _ => mapOver(t)
18961909 (flip(tp1p) relaxed_<:< flip(tp2p)) || viewExists(tp1, tp2)
18971910 else
1898- // New rules: better means generalize, givens (and extensions) always beat implicits
1899- if alt1IsImplicit != alt2IsImplicit then alt2IsImplicit
1900- else (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
1911+ (tp2p relaxed_<:< tp1p) || viewExists(tp2, tp1)
19011912 end isAsGoodValueType
19021913
19031914 /** Widen the result type of synthetic given methods from the implementation class to the
@@ -1968,13 +1979,19 @@ trait Applications extends Compatibility {
19681979 // alternatives are the same after following ExprTypes, pick one of them
19691980 // (prefer the one that is not a method, but that's arbitrary).
19701981 if alt1.widenExpr =:= alt2 then - 1 else 1
1971- else ownerScore match
1972- case 1 => if winsType1 || ! winsType2 then 1 else 0
1973- case - 1 => if winsType2 || ! winsType1 then - 1 else 0
1974- case 0 =>
1975- if winsType1 != winsType2 then if winsType1 then 1 else - 1
1976- else if alt1.symbol == alt2.symbol then comparePrefixes
1977- 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
19781995 end compareWithTypes
19791996
19801997 if alt1.symbol.is(ConstructorProxy ) && ! alt2.symbol.is(ConstructorProxy ) then - 1
0 commit comments