@@ -1803,7 +1803,8 @@ trait Applications extends Compatibility {
18031803   *  an alternative that takes more implicit parameters wins over one 
18041804   *  that takes fewer. 
18051805   */  
1806-   def  compare (alt1 : TermRef , alt2 : TermRef , preferGeneral : Boolean  =  false )(using  Context ):  Int  =  trace(i " compare( $alt1,  $alt2) " , overload) {
1806+   def  compare (alt1 : TermRef , alt2 : TermRef , preferGeneral : Boolean  =  false , needsEta : Boolean  =  false )(using  Context ):  Int  = 
1807+   trace(i " compare( $alt1,  $alt2) " , overload) {
18071808    record(" resolveOverloaded.compare"  )
18081809    val  scheme  = 
18091810      val  oldResolution  =  ctx.mode.is(Mode .OldImplicitResolution )
@@ -1818,30 +1819,34 @@ trait Applications extends Compatibility {
18181819    /**  Is alternative `alt1` with type `tp1` as good as alternative 
18191820     *  `alt2` with type `tp2` ? 
18201821     * 
1821-      *    1. A method `alt1` of type `(p1: T1, ..., pn: Tn)U` is as good as `alt2` 
1822-      *       if `alt1` is nullary or `alt2` is applicable to arguments (p1, ..., pn) of 
1823-      *       types T1,...,Tn. If the last parameter `pn` has a vararg type T*, then 
1822+      *    1. A method `alt1` of type `(p1: T1, ..., pn: Tn)U` is as good as `alt2` if: 
1823+      *       a. `alt1` is nullary, or 
1824+      *       b. `alt2` is applicable to arguments (p1, ..., pn) of types T1,...,Tn, or 
1825+      *       c. eta-expanded `alt1` is as good as `alt2` (when needing eta-expansion). 
1826+      *       When testing method applicability (1b), if the last parameter `pn` has a vararg type T*, then 
18241827     *       `alt1` must be applicable to arbitrary numbers of `T` parameters (which 
18251828     *       implies that it must be a varargs method as well). 
18261829     *    2. A polymorphic member of type [a1 >: L1 <: U1, ..., an >: Ln <: Un]T is as 
18271830     *       good as `alt2` of type `tp2` if T is as good as `tp2` under the 
18281831     *       assumption that for i = 1,...,n each ai is an abstract type name bounded 
18291832     *       from below by Li and from above by Ui. 
18301833     *    3. A member of any other type `tp1` is: 
1831-      *       a. always as good as a method or a polymorphic method. 
1832-      *       b. as good as a member of any other type `tp2` if `asGoodValueType(tp1, tp2) = true` 
1834+      *       a. as good as an eta-expanded `tp2` method (when needing eta-expansion) 
1835+      *       b. always as good as a (not eta-expanded) method or a polymorphic method. 
1836+      *       c. as good as a member of any other type `tp2` if `asGoodValueType(tp1, tp2) = true` 
18331837     */  
18341838    def  isAsGood (alt1 : TermRef , tp1 : Type , alt2 : TermRef , tp2 : Type ):  Boolean  =  trace(i " isAsGood  $tp1  $tp2" , overload) {
18351839      tp1 match 
18361840        case  tp1 : MethodType  =>  //  (1)
1837-           tp1.paramInfos.isEmpty &&  tp2.isInstanceOf [LambdaType ] 
1841+           tp1.paramInfos.isEmpty &&  tp2.isInstanceOf [MethodOrPoly ]  //  (1a) 
18381842          ||  {
18391843            if  tp1.isVarArgsMethod then 
18401844              tp2.isVarArgsMethod
1841-               &&  isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType , ArgMatch .Compatible )
1845+               &&  isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType , ArgMatch .Compatible )  //  (1b) 
18421846            else 
1843-               isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType , ArgMatch .Compatible )
1847+               isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType , ArgMatch .Compatible )  //  (1b) 
18441848          }
1849+           ||  needsEta &&  ! tp2.isInstanceOf [MethodOrPoly ] &&  isAsGood(alt1, tp1.toFunctionType(), alt2, tp2) //  (1c)
18451850        case  tp1 : PolyType  =>  //  (2)
18461851          inContext(ctx.fresh.setExploreTyperState()) {
18471852            //  Fully define the PolyType parameters so that the infos of the
@@ -1859,11 +1864,12 @@ trait Applications extends Compatibility {
18591864          def  compareValues (tp2 : Type )(using  Context ) = 
18601865            isAsGoodValueType(tp1, tp2, alt1.symbol.is(Implicit ))
18611866          tp2 match 
1862-             case  tp2 : MethodType  =>  true  //  (3a)
1863-             case  tp2 : PolyType  if  tp2.resultType.isInstanceOf [MethodType ] =>  true  //  (3a)
1864-             case  tp2 : PolyType  =>  //  (3b)
1867+             case  tp2 : MethodType  if  needsEta =>  isAsGood(alt1, tp1, alt2, tp2.toFunctionType()) //  (3a)
1868+             case  tp2 : MethodType  =>  true  //  (3b)
1869+             case  tp2 : PolyType  if  tp2.resultType.isInstanceOf [MethodType ] =>  true  //  (3b)
1870+             case  tp2 : PolyType  =>  //  (3c)
18651871              explore(compareValues(instantiateWithTypeVars(tp2)))
1866-             case  _ =>  //  3b )
1872+             case  _ =>  //  (3c )
18671873              compareValues(tp2)
18681874    }
18691875
@@ -2037,21 +2043,21 @@ trait Applications extends Compatibility {
20372043  }
20382044  end  compare 
20392045
2040-   def  narrowMostSpecific (alts : List [TermRef ])(using  Context ):  List [TermRef ] =  {
2046+   def  narrowMostSpecific (alts : List [TermRef ],  needsEta :  Boolean )(using  Context ):  List [TermRef ] =  {
20412047    record(" narrowMostSpecific"  )
20422048    alts match  {
20432049      case  Nil  =>  alts
20442050      case  _ ::  Nil  =>  alts
20452051      case  alt1 ::  alt2 ::  Nil  => 
2046-         compare(alt1, alt2) match  {
2052+         compare(alt1, alt2, needsEta  =  needsEta ) match  {
20472053          case   1  =>  alt1 ::  Nil 
20482054          case  - 1  =>  alt2 ::  Nil 
20492055          case   0  =>  alts
20502056        }
20512057      case  alt ::  alts1 => 
20522058        def  survivors (previous : List [TermRef ], alts : List [TermRef ]):  List [TermRef ] =  alts match  {
20532059          case  alt ::  alts1 => 
2054-             compare(previous.head, alt) match  {
2060+             compare(previous.head, alt, needsEta  =  needsEta ) match  {
20552061              case   1  =>  survivors(previous, alts1)
20562062              case  - 1  =>  survivors(alt ::  previous.tail, alts1)
20572063              case   0  =>  survivors(alt ::  previous, alts1)
@@ -2061,7 +2067,7 @@ trait Applications extends Compatibility {
20612067        val  best  ::  rest =  survivors(alt ::  Nil , alts1):  @ unchecked
20622068        def  asGood (alts : List [TermRef ]):  List [TermRef ] =  alts match  {
20632069          case  alt ::  alts1 => 
2064-             if  (compare(alt, best) <  0 ) asGood(alts1) else  alt ::  asGood(alts1)
2070+             if  (compare(alt, best, needsEta  =  needsEta ) <  0 ) asGood(alts1) else  alt ::  asGood(alts1)
20652071          case  nil => 
20662072            Nil 
20672073        }
@@ -2374,7 +2380,8 @@ trait Applications extends Compatibility {
23742380      //  If `pt` is erroneous, don't try to go further; report the error in `pt` instead.
23752381      candidates
23762382    else 
2377-       val  found  =  narrowMostSpecific(candidates)
2383+       val  needsEta  =  defn.isFunctionNType(pt.underlyingApplied)
2384+       val  found  =  narrowMostSpecific(candidates, needsEta)
23782385      if  found.length <=  1  then  found
23792386      else 
23802387        val  deepPt  =  pt.deepenProto
0 commit comments