@@ -1163,7 +1163,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
11631163 /** Is given method reference applicable to type arguments `targs` and argument trees `args`?
11641164 * @param resultType The expected result type of the application
11651165 */
1166- def isApplicable (methRef : TermRef , targs : List [Type ], args : List [Tree ], resultType : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
1166+ def isApplicableMethodRef (methRef : TermRef , targs : List [Type ], args : List [Tree ], resultType : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
11671167 def isApp (implicit ctx : Context ): Boolean =
11681168 new ApplicableToTrees (methRef, targs, args, resultType).success
11691169 if (keepConstraint) isApp else ctx.test(implicit ctx => isApp)
@@ -1172,43 +1172,47 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
11721172 /** Is given method reference applicable to type arguments `targs` and argument trees `args` without inferring views?
11731173 * @param resultType The expected result type of the application
11741174 */
1175- def isDirectlyApplicable (methRef : TermRef , targs : List [Type ], args : List [Tree ], resultType : Type )(implicit ctx : Context ): Boolean =
1175+ def isDirectlyApplicableMethodRef (methRef : TermRef , targs : List [Type ], args : List [Tree ], resultType : Type )(implicit ctx : Context ): Boolean =
11761176 ctx.test(implicit ctx => new ApplicableToTreesDirectly (methRef, targs, args, resultType).success)
11771177
11781178 /** Is given method reference applicable to argument types `args`?
11791179 * @param resultType The expected result type of the application
11801180 */
1181- def isApplicable (methRef : TermRef , args : List [Type ], resultType : Type )(implicit ctx : Context ): Boolean =
1181+ def isApplicableMethodRef (methRef : TermRef , args : List [Type ], resultType : Type )(implicit ctx : Context ): Boolean =
11821182 ctx.test(implicit ctx => new ApplicableToTypes (methRef, args, resultType).success)
11831183
11841184 /** Is given type applicable to type arguments `targs` and argument trees `args`,
11851185 * possibly after inserting an `apply`?
11861186 * @param resultType The expected result type of the application
11871187 */
1188- def isApplicable (tp : Type , targs : List [Type ], args : List [Tree ], resultType : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean =
1189- onMethod(tp, isApplicable(_, targs, args, resultType, keepConstraint))
1188+ def isApplicableType (tp : Type , targs : List [Type ], args : List [Tree ], resultType : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean =
1189+ onMethod(tp, targs.nonEmpty || args.nonEmpty) {
1190+ isApplicableMethodRef(_, targs, args, resultType, keepConstraint)
1191+ }
11901192
11911193 /** Is given type applicable to argument types `args`, possibly after inserting an `apply`?
11921194 * @param resultType The expected result type of the application
11931195 */
1194- def isApplicable (tp : Type , args : List [Type ], resultType : Type )(implicit ctx : Context ): Boolean =
1195- onMethod(tp, isApplicable(_, args, resultType))
1196+ def isApplicableType (tp : Type , args : List [Type ], resultType : Type )(implicit ctx : Context ): Boolean =
1197+ onMethod(tp, args.nonEmpty) {
1198+ isApplicableMethodRef(_, args, resultType)
1199+ }
11961200
1197- private def onMethod (tp : Type , p : TermRef => Boolean )(implicit ctx : Context ): Boolean = tp match {
1201+ private def onMethod (tp : Type , followApply : Boolean )( p : TermRef => Boolean )(implicit ctx : Context ): Boolean = tp match {
11981202 case methRef : TermRef if methRef.widenSingleton.isInstanceOf [MethodicType ] =>
11991203 p(methRef)
12001204 case mt : MethodicType =>
12011205 p(mt.narrow)
12021206 case _ =>
1203- tp.member(nme.apply).hasAltWith(d => p(TermRef (tp, nme.apply, d)))
1207+ followApply && tp.member(nme.apply).hasAltWith(d => p(TermRef (tp, nme.apply, d)))
12041208 }
12051209
12061210 /** Does `tp` have an extension method named `name` with this-argument `argType` and
12071211 * result matching `resultType`?
12081212 */
12091213 def hasExtensionMethod (tp : Type , name : TermName , argType : Type , resultType : Type )(implicit ctx : Context ) = {
12101214 def qualifies (mbr : Denotation ) =
1211- mbr.exists && isApplicable (tp.select(name, mbr), argType :: Nil , resultType)
1215+ mbr.exists && isApplicableType (tp.select(name, mbr), argType :: Nil , resultType)
12121216 tp.memberBasedOnFlags(name, required = ExtensionMethod ) match {
12131217 case mbr : SingleDenotation => qualifies(mbr)
12141218 case mbr => mbr.hasAltWith(qualifies(_))
@@ -1272,7 +1276,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
12721276 val formals1 =
12731277 if (tp1.isVarArgsMethod && tp2.isVarArgsMethod) tp1.paramInfos.map(_.repeatedToSingle)
12741278 else tp1.paramInfos
1275- isApplicable (alt2, formals1, WildcardType ) ||
1279+ isApplicableMethodRef (alt2, formals1, WildcardType ) ||
12761280 tp1.paramInfos.isEmpty && tp2.isInstanceOf [LambdaType ]
12771281 case tp1 : PolyType => // (2)
12781282 val nestedCtx = ctx.fresh.setExploreTyperState()
@@ -1454,7 +1458,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
14541458 * possibly also type argument `targs` that need to be applied to each alternative
14551459 * to form the method type.
14561460 * Two trials: First, without implicits or SAM conversions enabled. Then,
1457- * if the fist finds no eligible candidates, with implicits and SAM conversions enabled.
1461+ * if the first finds no eligible candidates, with implicits and SAM conversions enabled.
14581462 */
14591463 def resolveOverloaded (alts : List [TermRef ], pt : Type )(implicit ctx : Context ): List [TermRef ] = track(" resolveOverloaded" ) {
14601464
@@ -1485,7 +1489,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
14851489 * probability of pruning the search. result type comparisons are neither cheap nor
14861490 * do they prune much, on average.
14871491 */
1488- def adaptByResult (chosen : TermRef ) = pt match {
1492+ def adaptByResult (chosen : TermRef , alts : List [ TermRef ] ) = pt match {
14891493 case pt : FunProto if ! ctx.test(implicit ctx => resultConforms(chosen.symbol, chosen, pt.resultType)) =>
14901494 val conformingAlts = alts.filter(alt =>
14911495 (alt ne chosen) && ctx.test(implicit ctx => resultConforms(alt.symbol, alt, pt.resultType)))
@@ -1501,13 +1505,42 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
15011505 case _ => chosen
15021506 }
15031507
1504- var found = resolveOverloaded(alts, pt, Nil )(ctx.retractMode(Mode .ImplicitsEnabled ))
1505- if (found.isEmpty && ctx.mode.is(Mode .ImplicitsEnabled ))
1506- found = resolveOverloaded(alts, pt, Nil )
1507- found match {
1508- case alt :: Nil => adaptByResult(alt) :: Nil
1509- case _ => found
1508+ def resolve (alts : List [TermRef ]) = {
1509+ var found = resolveOverloaded(alts, pt, Nil )(ctx.retractMode(Mode .ImplicitsEnabled ))
1510+ if (found.isEmpty && ctx.mode.is(Mode .ImplicitsEnabled ))
1511+ found = resolveOverloaded(alts, pt, Nil )
1512+ found match {
1513+ case alt :: Nil => adaptByResult(alt, alts) :: Nil
1514+ case _ => found
1515+ }
1516+ }
1517+
1518+ /** Try an apply method, if
1519+ * - the result is applied to value arguments and alternative is not a method, or
1520+ * - the result is applied to type arguments and alternative is not polymorphic
1521+ */
1522+ val tryApply : Type => Boolean = alt => pt match {
1523+ case pt : FunProto => ! alt.widen.stripPoly.isInstanceOf [MethodType ]
1524+ case pt : PolyProto => ! alt.widen.isInstanceOf [PolyType ]
1525+ case _ => false
15101526 }
1527+
1528+ /** Replace each alternative by its apply members where necessary */
1529+ def applyMembers (alt : TermRef ): List [TermRef ] =
1530+ if (tryApply(alt)) alt.member(nme.apply).alternatives.map(TermRef (alt, nme.apply, _))
1531+ else alt :: Nil
1532+
1533+ /** Fall back from an apply method to its original alternative */
1534+ def retract (alt : TermRef ): TermRef =
1535+ if (alt.name == nme.apply && ! alts.contains(alt))
1536+ alts.find(_.symbol == alt.prefix.termSymbol).getOrElse(alt)
1537+ else alt
1538+
1539+ if (alts.exists(tryApply)) {
1540+ val expanded = alts.flatMap(applyMembers)
1541+ resolve(expanded).map(retract)
1542+ }
1543+ else resolve(alts)
15111544 }
15121545
15131546 /** This private version of `resolveOverloaded` does the bulk of the work of
@@ -1541,7 +1574,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
15411574 }
15421575
15431576 def narrowByTypes (alts : List [TermRef ], argTypes : List [Type ], resultType : Type ): List [TermRef ] =
1544- alts filter (isApplicable (_, argTypes, resultType))
1577+ alts filter (isApplicableMethodRef (_, argTypes, resultType))
15451578
15461579 val candidates = pt match {
15471580 case pt @ FunProto (args, resultType) =>
@@ -1551,7 +1584,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
15511584 case x => x
15521585 }
15531586
1554- def sizeFits (alt : TermRef , tp : Type ): Boolean = tp .stripPoly match {
1587+ def sizeFits (alt : TermRef ): Boolean = alt.widen .stripPoly match {
15551588 case tp : MethodType =>
15561589 val ptypes = tp.paramInfos
15571590 val numParams = ptypes.length
@@ -1566,7 +1599,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
15661599 }
15671600
15681601 def narrowBySize (alts : List [TermRef ]): List [TermRef ] =
1569- alts filter (alt => sizeFits(alt, alt.widen ))
1602+ alts. filter( sizeFits(_ ))
15701603
15711604 def narrowByShapes (alts : List [TermRef ]): List [TermRef ] = {
15721605 if (normArgs exists untpd.isFunctionWithUnknownParamType)
@@ -1578,11 +1611,11 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
15781611
15791612 def narrowByTrees (alts : List [TermRef ], args : List [Tree ], resultType : Type ): List [TermRef ] = {
15801613 val alts2 = alts.filter(alt =>
1581- isDirectlyApplicable (alt, targs, args, resultType)
1614+ isDirectlyApplicableMethodRef (alt, targs, args, resultType)
15821615 )
15831616 if (alts2.isEmpty && ! ctx.isAfterTyper)
15841617 alts.filter(alt =>
1585- isApplicable (alt, targs, args, resultType, keepConstraint = false )
1618+ isApplicableMethodRef (alt, targs, args, resultType, keepConstraint = false )
15861619 )
15871620 else
15881621 alts2
@@ -1825,4 +1858,3 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
18251858 app
18261859 }
18271860}
1828-
0 commit comments