@@ -1762,6 +1762,17 @@ trait Applications extends Compatibility {
17621762 else if sym2.is(Module ) then compareOwner(sym1, cls2)
17631763 else 0
17641764
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.4, 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+
17651776 /** Compare two alternatives of an overloaded call or an implicit search.
17661777 *
17671778 * @param alt1, alt2 Non-overloaded references indicating the two choices
@@ -1788,6 +1799,15 @@ trait Applications extends Compatibility {
17881799 */
17891800 def compare (alt1 : TermRef , alt2 : TermRef , preferGeneral : Boolean = false )(using Context ): Int = trace(i " compare( $alt1, $alt2) " , overload) {
17901801 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.4`)
1807+ || oldResolution
1808+ || alt1.symbol.is(Implicit ) && alt2.symbol.is(Implicit )
1809+ then CompareScheme .Intermediate
1810+ else CompareScheme .New
17911811
17921812 /** Is alternative `alt1` with type `tp1` as good as alternative
17931813 * `alt2` with type `tp2` ?
@@ -1830,15 +1850,15 @@ trait Applications extends Compatibility {
18301850 isAsGood(alt1, tp1.instantiate(tparams.map(_.typeRef)), alt2, tp2)
18311851 }
18321852 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 ))
18351855 tp2 match
18361856 case tp2 : MethodType => true // (3a)
18371857 case tp2 : PolyType if tp2.resultType.isInstanceOf [MethodType ] => true // (3a)
18381858 case tp2 : PolyType => // (3b)
1839- explore(compareValues(tp1, instantiateWithTypeVars(tp2)))
1859+ explore(compareValues(instantiateWithTypeVars(tp2)))
18401860 case _ => // 3b)
1841- compareValues(tp1, tp2)
1861+ compareValues(tp2)
18421862 }
18431863
18441864 /** Test whether value type `tp1` is as good as value type `tp2`.
@@ -1876,9 +1896,8 @@ trait Applications extends Compatibility {
18761896 * Also and only for given resolution: If a compared type refers to a given or its module class, use
18771897 * the intersection of its parent classes instead.
18781898 */
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
18821901 // Normal specificity test for overloading resolution (where `preferGeneral` is false)
18831902 // and in mode Scala3-migration when we compare with the old Scala 2 rules.
18841903 isCompatible(tp1, tp2)
@@ -1892,13 +1911,7 @@ trait Applications extends Compatibility {
18921911 val tp1p = prepare(tp1)
18931912 val tp2p = prepare(tp2)
18941913
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
19021915 val flip = new TypeMap :
19031916 def apply (t : Type ) = t match
19041917 case t @ AppliedType (tycon, args) =>
@@ -1909,9 +1922,7 @@ trait Applications extends Compatibility {
19091922 case _ => mapOver(t)
19101923 (flip(tp1p) relaxed_<:< flip(tp2p)) || viewExists(tp1, tp2)
19111924 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)
19151926 end isAsGoodValueType
19161927
19171928 /** Widen the result type of synthetic given methods from the implementation class to the
@@ -1982,13 +1993,19 @@ trait Applications extends Compatibility {
19821993 // alternatives are the same after following ExprTypes, pick one of them
19831994 // (prefer the one that is not a method, but that's arbitrary).
19841995 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
19922009 end compareWithTypes
19932010
19942011 if alt1.symbol.is(ConstructorProxy ) && ! alt2.symbol.is(ConstructorProxy ) then - 1
0 commit comments