@@ -833,7 +833,7 @@ trait Applications extends Compatibility {
833
833
def typedApply (tree : untpd.Apply , pt : Type )(implicit ctx : Context ): Tree = {
834
834
835
835
def realApply (implicit ctx : Context ): Tree = {
836
- val originalProto = new FunProto (tree.args, IgnoredProto (pt))(this , tree.isGivenApply )(argCtx(tree))
836
+ val originalProto = new FunProto (tree.args, IgnoredProto (pt))(this , tree.isUsingApply )(argCtx(tree))
837
837
record(" typedApply" )
838
838
val fun1 = typedFunPart(tree.fun, originalProto)
839
839
@@ -1299,6 +1299,16 @@ trait Applications extends Compatibility {
1299
1299
}
1300
1300
}
1301
1301
1302
+ /** Drop any implicit parameter section */
1303
+ def stripImplicit (tp : Type )(using Context ): Type = tp match {
1304
+ case mt : MethodType if mt.isImplicitMethod =>
1305
+ stripImplicit(resultTypeApprox(mt))
1306
+ case pt : PolyType =>
1307
+ pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType))
1308
+ case _ =>
1309
+ tp
1310
+ }
1311
+
1302
1312
/** Compare owner inheritance level.
1303
1313
* @param sym1 The first owner
1304
1314
* @param sym2 The second owner
@@ -1466,16 +1476,6 @@ trait Applications extends Compatibility {
1466
1476
else tp
1467
1477
}
1468
1478
1469
- /** Drop any implicit parameter section */
1470
- def stripImplicit (tp : Type ): Type = tp match {
1471
- case mt : MethodType if mt.isImplicitMethod =>
1472
- stripImplicit(resultTypeApprox(mt))
1473
- case pt : PolyType =>
1474
- pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType))
1475
- case _ =>
1476
- tp
1477
- }
1478
-
1479
1479
def compareWithTypes (tp1 : Type , tp2 : Type ) = {
1480
1480
val ownerScore = compareOwner(alt1.symbol.maybeOwner, alt2.symbol.maybeOwner)
1481
1481
def winsType1 = isAsSpecific(alt1, tp1, alt2, tp2)
@@ -1707,6 +1707,22 @@ trait Applications extends Compatibility {
1707
1707
case _ => arg
1708
1708
end normArg
1709
1709
1710
+ /** Resolve overloading by mapping to a different problem where each alternative's
1711
+ * type is mapped with `f`, alternatives with non-existing types are dropped, and the
1712
+ * expected type is `pt`. Map the results back to the original alternatives.
1713
+ */
1714
+ def resolveMapped (alts : List [TermRef ], f : TermRef => Type , pt : Type ): List [TermRef ] =
1715
+ val reverseMapping = alts.flatMap { alt =>
1716
+ val t = f(alt)
1717
+ if t.exists then
1718
+ Some ((TermRef (NoPrefix , alt.symbol.asTerm.copy(info = t)), alt))
1719
+ else
1720
+ None
1721
+ }
1722
+ val mapped = reverseMapping.map(_._1)
1723
+ overload.println(i " resolve mapped: $mapped" )
1724
+ resolveOverloaded(mapped, pt, targs).map(reverseMapping.toMap)
1725
+
1710
1726
val candidates = pt match {
1711
1727
case pt @ FunProto (args, resultType) =>
1712
1728
val numArgs = args.length
@@ -1747,6 +1763,15 @@ trait Applications extends Compatibility {
1747
1763
alts2
1748
1764
}
1749
1765
1766
+ if pt.isUsingApply then
1767
+ val alts0 = alts.filterConserve { alt =>
1768
+ val mt = alt.widen.stripPoly
1769
+ mt.isImplicitMethod || mt.isContextualMethod
1770
+ }
1771
+ if alts0 ne alts then return resolveOverloaded(alts0, pt, targs)
1772
+ else if alts.exists(_.widen.stripPoly.isContextualMethod) then
1773
+ return resolveMapped(alts, alt => stripImplicit(alt.widen), pt)
1774
+
1750
1775
val alts1 = narrowBySize(alts)
1751
1776
// ctx.log(i"narrowed by size: ${alts1.map(_.symbol.showDcl)}%, %")
1752
1777
if isDetermined(alts1) then alts1
@@ -1783,32 +1808,20 @@ trait Applications extends Compatibility {
1783
1808
else compat
1784
1809
}
1785
1810
1786
- /** For each candidate `C`, a proxy termref paired with `C`.
1787
- * The proxy termref has as symbol a copy of the original candidate symbol,
1788
- * with an info that strips the first value parameter list away.
1789
- * @param argTypes The types of the arguments of the FunProto `pt`.
1811
+ /** The type of alternative `alt` after instantiating its first parameter
1812
+ * clause with `argTypes`.
1790
1813
*/
1791
- def advanceCandidates (argTypes : List [Type ]): List [( TermRef , TermRef )] = {
1792
- def strippedType (tp : Type ): Type = tp match {
1814
+ def skipParamClause (argTypes : List [Type ])( alt : TermRef ) : Type =
1815
+ def skip (tp : Type ): Type = tp match {
1793
1816
case tp : PolyType =>
1794
- val rt = strippedType (tp.resultType)
1817
+ val rt = skip (tp.resultType)
1795
1818
if (rt.exists) tp.derivedLambdaType(resType = rt) else rt
1796
1819
case tp : MethodType =>
1797
1820
tp.instantiate(argTypes)
1798
1821
case _ =>
1799
1822
NoType
1800
1823
}
1801
- def cloneCandidate (cand : TermRef ): List [(TermRef , TermRef )] = {
1802
- val strippedInfo = strippedType(cand.widen)
1803
- if (strippedInfo.exists) {
1804
- val sym = cand.symbol.asTerm.copy(info = strippedInfo)
1805
- (TermRef (NoPrefix , sym), cand) :: Nil
1806
- }
1807
- else Nil
1808
- }
1809
- overload.println(i " look at more params: ${candidates.head.symbol}: ${candidates.map(_.widen)}%, % with $pt, [ $targs%, %] " )
1810
- candidates.flatMap(cloneCandidate)
1811
- }
1824
+ skip(alt.widen)
1812
1825
1813
1826
def resultIsMethod (tp : Type ): Boolean = tp.widen.stripPoly match
1814
1827
case tp : MethodType => tp.resultType.isInstanceOf [MethodType ]
@@ -1821,9 +1834,7 @@ trait Applications extends Compatibility {
1821
1834
deepPt match
1822
1835
case pt @ FunProto (_, resType : FunProto ) =>
1823
1836
// try to narrow further with snd argument list
1824
- val advanced = advanceCandidates(pt.typedArgs().tpes)
1825
- resolveOverloaded(advanced.map(_._1), resType, Nil ) // resolve with candidates where first params are stripped
1826
- .map(advanced.toMap) // map surviving result(s) back to original candidates
1837
+ resolveMapped(candidates, skipParamClause(pt.typedArgs().tpes), resType)
1827
1838
case _ =>
1828
1839
// prefer alternatives that need no eta expansion
1829
1840
val noCurried = alts.filter(! resultIsMethod(_))
0 commit comments