@@ -650,8 +650,8 @@ trait Applications extends Compatibility {
650
650
/** Subclass of Application for applicability tests with type arguments and value
651
651
* argument trees.
652
652
*/
653
- class ApplicableToTrees (methRef : TermRef , targs : List [ Type ], args : List [Tree ], resultType : Type )(implicit ctx : Context )
654
- extends TestApplication (methRef, methRef.widen.appliedTo(targs) , args, resultType) {
653
+ class ApplicableToTrees (methRef : TermRef , args : List [Tree ], resultType : Type )(implicit ctx : Context )
654
+ extends TestApplication (methRef, methRef.widen, args, resultType) {
655
655
def argType (arg : Tree , formal : Type ): Type = normalize(arg.tpe, formal)
656
656
def treeToArg (arg : Tree ): Tree = arg
657
657
def isVarArg (arg : Tree ): Boolean = tpd.isWildcardStarArg(arg)
@@ -662,7 +662,8 @@ trait Applications extends Compatibility {
662
662
/** Subclass of Application for applicability tests with type arguments and value
663
663
* argument trees.
664
664
*/
665
- class ApplicableToTreesDirectly (methRef : TermRef , targs : List [Type ], args : List [Tree ], resultType : Type )(implicit ctx : Context ) extends ApplicableToTrees (methRef, targs, args, resultType)(ctx) {
665
+ class ApplicableToTreesDirectly (methRef : TermRef , args : List [Tree ], resultType : Type )(implicit ctx : Context )
666
+ extends ApplicableToTrees (methRef, args, resultType)(ctx) {
666
667
override def argOK (arg : TypedArg , formal : Type ): Boolean =
667
668
argType(arg, formal) relaxed_<:< formal.widenExpr
668
669
}
@@ -1240,34 +1241,33 @@ trait Applications extends Compatibility {
1240
1241
def typedUnApply (tree : untpd.UnApply , selType : Type )(implicit ctx : Context ): UnApply =
1241
1242
throw new UnsupportedOperationException (" cannot type check an UnApply node" )
1242
1243
1243
- /** Is given method reference applicable to type arguments `targs` and argument trees `args`?
1244
+ /** Is given method reference applicable to argument trees `args`?
1244
1245
* @param resultType The expected result type of the application
1245
1246
*/
1246
- def isApplicableMethodRef (methRef : TermRef , targs : List [ Type ], args : List [Tree ], resultType : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
1247
+ def isApplicableMethodRef (methRef : TermRef , args : List [Tree ], resultType : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
1247
1248
def isApp (implicit ctx : Context ): Boolean =
1248
- new ApplicableToTrees (methRef, targs, args, resultType).success
1249
+ new ApplicableToTrees (methRef, args, resultType).success
1249
1250
if (keepConstraint) isApp else ctx.test(isApp)
1250
1251
}
1251
1252
1252
- /** Is given method reference applicable to type arguments `targs` and argument trees `args` without inferring views?
1253
+ /** Is given method reference applicable to argument trees `args` without inferring views?
1253
1254
* @param resultType The expected result type of the application
1254
1255
*/
1255
- def isDirectlyApplicableMethodRef (methRef : TermRef , targs : List [ Type ], args : List [Tree ], resultType : Type )(implicit ctx : Context ): Boolean =
1256
- ctx.test(new ApplicableToTreesDirectly (methRef, targs, args, resultType).success)
1256
+ def isDirectlyApplicableMethodRef (methRef : TermRef , args : List [Tree ], resultType : Type )(implicit ctx : Context ): Boolean =
1257
+ ctx.test(new ApplicableToTreesDirectly (methRef, args, resultType).success)
1257
1258
1258
1259
/** Is given method reference applicable to argument types `args`?
1259
1260
* @param resultType The expected result type of the application
1260
1261
*/
1261
1262
def isApplicableMethodRef (methRef : TermRef , args : List [Type ], resultType : Type )(implicit ctx : Context ): Boolean =
1262
1263
ctx.test(new ApplicableToTypes (methRef, args, resultType).success)
1263
1264
1264
- /** Is given type applicable to type arguments `targs` and argument trees `args`,
1265
- * possibly after inserting an `apply`?
1265
+ /** Is given type applicable to argument trees `args`, possibly after inserting an `apply`?
1266
1266
* @param resultType The expected result type of the application
1267
1267
*/
1268
- def isApplicableType (tp : Type , targs : List [ Type ], args : List [Tree ], resultType : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean =
1269
- onMethod(tp, targs.nonEmpty || args.nonEmpty) {
1270
- isApplicableMethodRef(_, targs, args, resultType, keepConstraint)
1268
+ def isApplicableType (tp : Type , args : List [Tree ], resultType : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean =
1269
+ onMethod(tp, args.nonEmpty) {
1270
+ isApplicableMethodRef(_, args, resultType, keepConstraint)
1271
1271
}
1272
1272
1273
1273
/** Is given type applicable to argument types `args`, possibly after inserting an `apply`?
@@ -1538,13 +1538,11 @@ trait Applications extends Compatibility {
1538
1538
}
1539
1539
}
1540
1540
1541
- /** Resolve overloaded alternative `alts`, given expected type `pt` and
1542
- * possibly also type argument `targs` that need to be applied to each alternative
1543
- * to form the method type.
1541
+ /** Resolve overloaded alternative `alts`, given expected type `pt`.
1544
1542
* Two trials: First, without implicits or SAM conversions enabled. Then,
1545
1543
* if the first finds no eligible candidates, with implicits and SAM conversions enabled.
1546
1544
*/
1547
- def resolveOverloaded (alts : List [TermRef ], pt : Type )(implicit ctx : Context ): List [TermRef ] = {
1545
+ def resolveOverloaded (alts : List [TermRef ], pt : Type )(implicit ctx : Context ): List [TermRef ] =
1548
1546
record(" resolveOverloaded" )
1549
1547
1550
1548
/** Is `alt` a method or polytype whose result type after the first value parameter
@@ -1590,15 +1588,26 @@ trait Applications extends Compatibility {
1590
1588
case _ => chosen
1591
1589
}
1592
1590
1593
- def resolve (alts : List [TermRef ]) = {
1594
- var found = resolveOverloaded(alts, pt, Nil )(ctx.retractMode(Mode .ImplicitsEnabled ))
1595
- if (found.isEmpty && ctx.mode.is(Mode .ImplicitsEnabled ))
1596
- found = resolveOverloaded(alts, pt, Nil )
1597
- found match {
1591
+ def resolve (alts : List [TermRef ]): List [TermRef ] =
1592
+ pt match
1593
+ case pt : FunProto =>
1594
+ if pt.isUsingApply then
1595
+ val alts0 = alts.filterConserve { alt =>
1596
+ val mt = alt.widen.stripPoly
1597
+ mt.isImplicitMethod || mt.isContextualMethod
1598
+ }
1599
+ if alts0 ne alts then return resolve(alts0)
1600
+ else if alts.exists(_.widen.stripPoly.isContextualMethod) then
1601
+ return resolveMapped(alts, alt => stripImplicit(alt.widen), pt)
1602
+ case _ =>
1603
+
1604
+ var found = resolveOverloaded1(alts, pt)(using ctx.retractMode(Mode .ImplicitsEnabled ))
1605
+ if found.isEmpty && ctx.mode.is(Mode .ImplicitsEnabled ) then
1606
+ found = resolveOverloaded1(alts, pt)
1607
+ found match
1598
1608
case alt :: Nil => adaptByResult(alt, alts) :: Nil
1599
1609
case _ => found
1600
- }
1601
- }
1610
+ end resolve
1602
1611
1603
1612
/** Try an apply method, if
1604
1613
* - the result is applied to value arguments and alternative is not a method, or
@@ -1634,15 +1643,16 @@ trait Applications extends Compatibility {
1634
1643
resolve(expanded).map(retract)
1635
1644
}
1636
1645
else resolve(alts)
1637
- }
1646
+ end resolveOverloaded
1638
1647
1639
1648
/** This private version of `resolveOverloaded` does the bulk of the work of
1640
- * overloading resolution, but does not do result adaptation. It might be
1641
- * called twice from the public `resolveOverloaded` method, once with
1649
+ * overloading resolution, but does neither result adaptation nor apply insertion.
1650
+ * It might be called twice from the public `resolveOverloaded` method, once with
1642
1651
* implicits and SAM conversions enabled, and once without.
1643
1652
*/
1644
- private def resolveOverloaded (alts : List [TermRef ], pt : Type , targs : List [Type ])(implicit ctx : Context ): List [TermRef ] =
1645
- record(" resolveOverloaded/2" )
1653
+ private def resolveOverloaded1 (alts : List [TermRef ], pt : Type )(implicit ctx : Context ): List [TermRef ] =
1654
+ trace(i " resolve over $alts%, %, pt = $pt" , typr, show = true ) {
1655
+ record(" resolveOverloaded1" )
1646
1656
1647
1657
def isDetermined (alts : List [TermRef ]) = alts.isEmpty || alts.tail.isEmpty
1648
1658
@@ -1707,22 +1717,6 @@ trait Applications extends Compatibility {
1707
1717
case _ => arg
1708
1718
end normArg
1709
1719
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
-
1726
1720
val candidates = pt match {
1727
1721
case pt @ FunProto (args, resultType) =>
1728
1722
val numArgs = args.length
@@ -1753,25 +1747,16 @@ trait Applications extends Compatibility {
1753
1747
1754
1748
def narrowByTrees (alts : List [TermRef ], args : List [Tree ], resultType : Type ): List [TermRef ] = {
1755
1749
val alts2 = alts.filter(alt =>
1756
- isDirectlyApplicableMethodRef(alt, targs, args, resultType)
1750
+ isDirectlyApplicableMethodRef(alt, args, resultType)
1757
1751
)
1758
1752
if (alts2.isEmpty && ! ctx.isAfterTyper)
1759
1753
alts.filter(alt =>
1760
- isApplicableMethodRef(alt, targs, args, resultType, keepConstraint = false )
1754
+ isApplicableMethodRef(alt, args, resultType, keepConstraint = false )
1761
1755
)
1762
1756
else
1763
1757
alts2
1764
1758
}
1765
1759
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
-
1775
1760
val alts1 = narrowBySize(alts)
1776
1761
// ctx.log(i"narrowed by size: ${alts1.map(_.symbol.showDcl)}%, %")
1777
1762
if isDetermined(alts1) then alts1
@@ -1783,9 +1768,10 @@ trait Applications extends Compatibility {
1783
1768
pretypeArgs(alts2, pt)
1784
1769
narrowByTrees(alts2, pt.typedArgs(normArg(alts2, _, _)), resultType)
1785
1770
1786
- case pt @ PolyProto (targs1, pt1) if targs.isEmpty =>
1787
- val alts1 = alts.filter(pt.isMatchedBy(_))
1788
- resolveOverloaded(alts1, pt1, targs1.tpes)
1771
+ case pt @ PolyProto (targs1, pt1) =>
1772
+ val alts1 = alts.filter(pt.canInstantiate)
1773
+ if isDetermined(alts1) then alts1
1774
+ else resolveMapped(alts1, _.widen.appliedTo(targs1.tpes), pt1)
1789
1775
1790
1776
case defn.FunctionOf (args, resultType, _, _) =>
1791
1777
narrowByTypes(alts, args, resultType)
@@ -1842,21 +1828,38 @@ trait Applications extends Compatibility {
1842
1828
if noCurriedCount == 1 then
1843
1829
noCurried
1844
1830
else if noCurriedCount > 1 && noCurriedCount < alts.length then
1845
- resolveOverloaded (noCurried, pt, targs )
1831
+ resolveOverloaded1 (noCurried, pt)
1846
1832
else
1847
1833
// prefer alternatves that match without default parameters
1848
1834
val noDefaults = alts.filter(! _.symbol.hasDefaultParams)
1849
1835
val noDefaultsCount = noDefaults.length
1850
1836
if noDefaultsCount == 1 then
1851
1837
noDefaults
1852
1838
else if noDefaultsCount > 1 && noDefaultsCount < alts.length then
1853
- resolveOverloaded (noDefaults, pt, targs )
1839
+ resolveOverloaded1 (noDefaults, pt)
1854
1840
else if deepPt ne pt then
1855
1841
// try again with a deeper known expected type
1856
- resolveOverloaded (alts, deepPt, targs )
1842
+ resolveOverloaded1 (alts, deepPt)
1857
1843
else
1858
1844
candidates
1859
- end resolveOverloaded
1845
+ }
1846
+ end resolveOverloaded1
1847
+
1848
+ /** Resolve overloading by mapping to a different problem where each alternative's
1849
+ * type is mapped with `f`, alternatives with non-existing types are dropped, and the
1850
+ * expected type is `pt`. Map the results back to the original alternatives.
1851
+ */
1852
+ def resolveMapped (alts : List [TermRef ], f : TermRef => Type , pt : Type )(using Context ): List [TermRef ] =
1853
+ val reverseMapping = alts.flatMap { alt =>
1854
+ val t = f(alt)
1855
+ if t.exists then
1856
+ Some ((TermRef (NoPrefix , alt.symbol.asTerm.copy(info = t)), alt))
1857
+ else
1858
+ None
1859
+ }
1860
+ val mapped = reverseMapping.map(_._1)
1861
+ overload.println(i " resolve mapped: $mapped" )
1862
+ resolveOverloaded(mapped, pt).map(reverseMapping.toMap)
1860
1863
1861
1864
/** Try to typecheck any arguments in `pt` that are function values missing a
1862
1865
* parameter type. If the formal parameter types corresponding to a closure argument
0 commit comments