@@ -612,18 +612,24 @@ trait Applications extends Compatibility {
612612 }
613613 }
614614
615+ /** The degree to which an argument has to match a formal parameter */
616+ enum ArgMatch :
617+ case SubType // argument is a relaxed subtype of formal
618+ case Compatible // argument is compatible with formal
619+ case CompatibleCAP // capture-converted argument is compatible with formal
620+
615621 /** Subclass of Application for the cases where we are interested only
616622 * in a "can/cannot apply" answer, without needing to construct trees or
617623 * issue error messages.
618624 */
619- abstract class TestApplication [Arg ](methRef : TermRef , funType : Type , args : List [Arg ], resultType : Type )(using Context )
625+ abstract class TestApplication [Arg ](methRef : TermRef , funType : Type , args : List [Arg ], resultType : Type , argMatch : ArgMatch )(using Context )
620626 extends Application [Arg ](methRef, funType, args, resultType) {
621627 type TypedArg = Arg
622628 type Result = Unit
623629
624630 def applyKind = ApplyKind .Regular
625631
626- protected def argOK (arg : TypedArg , formal : Type ): Boolean = argType(arg, formal) match {
632+ protected def argOK (arg : TypedArg , formal : Type ): Boolean = argType(arg, formal) match
627633 case ref : TermRef if ref.denot.isOverloaded =>
628634 // in this case we could not resolve overloading because no alternative
629635 // matches expected type
@@ -633,8 +639,17 @@ trait Applications extends Compatibility {
633639 case SAMType (sam) => argtpe <:< sam.toFunctionType(isJava = formal.classSymbol.is(JavaDefined ))
634640 case _ => false
635641 }
636- isCompatible(argtpe, formal) || ctx.mode.is(Mode .ImplicitsEnabled ) && SAMargOK
637- }
642+ if argMatch == ArgMatch .SubType then
643+ argtpe relaxed_<:< formal.widenExpr
644+ else
645+ isCompatible(argtpe, formal)
646+ || ctx.mode.is(Mode .ImplicitsEnabled ) && SAMargOK
647+ || argMatch == ArgMatch .CompatibleCAP
648+ && {
649+ val argtpe1 = argtpe.widen
650+ val captured = captureWildcards(argtpe1)
651+ (captured ne argtpe1) && isCompatible(captured, formal.widenExpr)
652+ }
638653
639654 /** The type of the given argument */
640655 protected def argType (arg : Arg , formal : Type ): Type
@@ -654,8 +669,8 @@ trait Applications extends Compatibility {
654669 /** Subclass of Application for applicability tests with type arguments and value
655670 * argument trees.
656671 */
657- class ApplicableToTrees (methRef : TermRef , args : List [Tree ], resultType : Type )(using Context )
658- extends TestApplication (methRef, methRef.widen, args, resultType) {
672+ class ApplicableToTrees (methRef : TermRef , args : List [Tree ], resultType : Type , argMatch : ArgMatch )(using Context )
673+ extends TestApplication (methRef, methRef.widen, args, resultType, argMatch ) {
659674 def argType (arg : Tree , formal : Type ): Type =
660675 if untpd.isContextualClosure(arg) && defn.isContextFunctionType(formal) then arg.tpe
661676 else normalize(arg.tpe, formal)
@@ -665,18 +680,9 @@ trait Applications extends Compatibility {
665680 def harmonizeArgs (args : List [Tree ]): List [Tree ] = harmonize(args)
666681 }
667682
668- /** Subclass of Application for applicability tests with type arguments and value
669- * argument trees.
670- */
671- class ApplicableToTreesDirectly (methRef : TermRef , args : List [Tree ], resultType : Type )(using Context )
672- extends ApplicableToTrees (methRef, args, resultType) {
673- override def argOK (arg : TypedArg , formal : Type ): Boolean =
674- argType(arg, formal) relaxed_<:< formal.widenExpr
675- }
676-
677683 /** Subclass of Application for applicability tests with value argument types. */
678- class ApplicableToTypes (methRef : TermRef , args : List [Type ], resultType : Type )(using Context )
679- extends TestApplication (methRef, methRef, args, resultType) {
684+ class ApplicableToTypes (methRef : TermRef , args : List [Type ], resultType : Type , argMatch : ArgMatch )(using Context )
685+ extends TestApplication (methRef, methRef, args, resultType, argMatch ) {
680686 def argType (arg : Type , formal : Type ): Type = arg
681687 def treeToArg (arg : Tree ): Type = arg.tpe
682688 def isVarArg (arg : Type ): Boolean = arg.isRepeatedParam
@@ -1323,38 +1329,32 @@ trait Applications extends Compatibility {
13231329 /** Is given method reference applicable to argument trees `args`?
13241330 * @param resultType The expected result type of the application
13251331 */
1326- def isApplicableMethodRef (methRef : TermRef , args : List [Tree ], resultType : Type , keepConstraint : Boolean )(using Context ): Boolean = {
1332+ def isApplicableMethodRef (methRef : TermRef , args : List [Tree ], resultType : Type , keepConstraint : Boolean , argMatch : ArgMatch )(using Context ): Boolean = {
13271333 def isApp (using Context ): Boolean =
1328- new ApplicableToTrees (methRef, args, resultType).success
1334+ new ApplicableToTrees (methRef, args, resultType, argMatch ).success
13291335 if (keepConstraint) isApp else explore(isApp)
13301336 }
13311337
1332- /** Is given method reference applicable to argument trees `args` without inferring views?
1333- * @param resultType The expected result type of the application
1334- */
1335- def isDirectlyApplicableMethodRef (methRef : TermRef , args : List [Tree ], resultType : Type )(using Context ): Boolean =
1336- explore(new ApplicableToTreesDirectly (methRef, args, resultType).success)
1337-
13381338 /** Is given method reference applicable to argument types `args`?
13391339 * @param resultType The expected result type of the application
13401340 */
1341- def isApplicableMethodRef (methRef : TermRef , args : List [Type ], resultType : Type )(using Context ): Boolean =
1342- explore(new ApplicableToTypes (methRef, args, resultType).success)
1341+ def isApplicableMethodRef (methRef : TermRef , args : List [Type ], resultType : Type , argMatch : ArgMatch )(using Context ): Boolean =
1342+ explore(new ApplicableToTypes (methRef, args, resultType, argMatch ).success)
13431343
13441344 /** Is given type applicable to argument trees `args`, possibly after inserting an `apply`?
13451345 * @param resultType The expected result type of the application
13461346 */
13471347 def isApplicableType (tp : Type , args : List [Tree ], resultType : Type , keepConstraint : Boolean )(using Context ): Boolean =
13481348 onMethod(tp, args.nonEmpty) {
1349- isApplicableMethodRef(_, args, resultType, keepConstraint)
1349+ isApplicableMethodRef(_, args, resultType, keepConstraint, ArgMatch . Compatible )
13501350 }
13511351
13521352 /** Is given type applicable to argument types `args`, possibly after inserting an `apply`?
13531353 * @param resultType The expected result type of the application
13541354 */
13551355 def isApplicableType (tp : Type , args : List [Type ], resultType : Type )(using Context ): Boolean =
13561356 onMethod(tp, args.nonEmpty) {
1357- isApplicableMethodRef(_, args, resultType)
1357+ isApplicableMethodRef(_, args, resultType, ArgMatch . Compatible )
13581358 }
13591359
13601360 private def onMethod (tp : Type , followApply : Boolean )(p : TermRef => Boolean )(using Context ): Boolean = tp match {
@@ -1485,9 +1485,9 @@ trait Applications extends Compatibility {
14851485 || {
14861486 if tp1.isVarArgsMethod then
14871487 tp2.isVarArgsMethod
1488- && isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType )
1488+ && isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType , ArgMatch . Compatible )
14891489 else
1490- isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType )
1490+ isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType , ArgMatch . Compatible )
14911491 }
14921492 case tp1 : PolyType => // (2)
14931493 inContext(ctx.fresh.setExploreTyperState()) {
@@ -1695,7 +1695,7 @@ trait Applications extends Compatibility {
16951695 */
16961696 def adaptByResult (chosen : TermRef , alts : List [TermRef ]) = pt match {
16971697 case pt : FunProto if ! explore(resultConforms(chosen.symbol, chosen, pt.resultType)) =>
1698- val conformingAlts = alts.filter (alt =>
1698+ val conformingAlts = alts.filterConserve (alt =>
16991699 (alt ne chosen) && explore(resultConforms(alt.symbol, alt, pt.resultType)))
17001700 conformingAlts match {
17011701 case Nil => chosen
@@ -1796,7 +1796,7 @@ trait Applications extends Compatibility {
17961796 }
17971797
17981798 def narrowByTypes (alts : List [TermRef ], argTypes : List [Type ], resultType : Type ): List [TermRef ] =
1799- alts filter (isApplicableMethodRef(_, argTypes, resultType))
1799+ alts.filterConserve (isApplicableMethodRef(_, argTypes, resultType, ArgMatch . CompatibleCAP ))
18001800
18011801 /** Normalization steps before checking arguments:
18021802 *
@@ -1865,11 +1865,11 @@ trait Applications extends Compatibility {
18651865
18661866 def narrowByTrees (alts : List [TermRef ], args : List [Tree ], resultType : Type ): List [TermRef ] = {
18671867 val alts2 = alts.filterConserve(alt =>
1868- isDirectlyApplicableMethodRef (alt, args, resultType)
1868+ isApplicableMethodRef (alt, args, resultType, keepConstraint = false , ArgMatch . SubType )
18691869 )
18701870 if (alts2.isEmpty && ! ctx.isAfterTyper)
18711871 alts.filterConserve(alt =>
1872- isApplicableMethodRef(alt, args, resultType, keepConstraint = false )
1872+ isApplicableMethodRef(alt, args, resultType, keepConstraint = false , ArgMatch . CompatibleCAP )
18731873 )
18741874 else
18751875 alts2
@@ -1890,7 +1890,7 @@ trait Applications extends Compatibility {
18901890 narrowByTrees(alts2, pt.typedArgs(normArg(alts2, _, _)), resultType)
18911891
18921892 case pt @ PolyProto (targs1, pt1) =>
1893- val alts1 = alts.filter (pt.canInstantiate)
1893+ val alts1 = alts.filterConserve (pt.canInstantiate)
18941894 if isDetermined(alts1) then alts1
18951895 else
18961896 def withinBounds (alt : TermRef ) = alt.widen match
@@ -1904,7 +1904,7 @@ trait Applications extends Compatibility {
19041904 narrowByTypes(alts, args, resultType)
19051905
19061906 case pt =>
1907- val compat = alts.filter (normalizedCompatible(_, pt, keepConstraint = false ))
1907+ val compat = alts.filterConserve (normalizedCompatible(_, pt, keepConstraint = false ))
19081908 if (compat.isEmpty)
19091909 /*
19101910 * the case should not be moved to the enclosing match
@@ -1967,15 +1967,15 @@ trait Applications extends Compatibility {
19671967 skipParamClause(pt.typedArgs().tpes, Nil ), resType)
19681968 case _ =>
19691969 // prefer alternatives that need no eta expansion
1970- val noCurried = alts.filter (! resultIsMethod(_))
1970+ val noCurried = alts.filterConserve (! resultIsMethod(_))
19711971 val noCurriedCount = noCurried.length
19721972 if noCurriedCount == 1 then
19731973 noCurried
19741974 else if noCurriedCount > 1 && noCurriedCount < alts.length then
19751975 resolveOverloaded1(noCurried, pt)
19761976 else
19771977 // prefer alternatves that match without default parameters
1978- val noDefaults = alts.filter (! _.symbol.hasDefaultParams)
1978+ val noDefaults = alts.filterConserve (! _.symbol.hasDefaultParams)
19791979 val noDefaultsCount = noDefaults.length
19801980 if noDefaultsCount == 1 then
19811981 noDefaults
0 commit comments