@@ -612,18 +612,24 @@ trait Applications extends Compatibility {
612
612
}
613
613
}
614
614
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
+
615
621
/** Subclass of Application for the cases where we are interested only
616
622
* in a "can/cannot apply" answer, without needing to construct trees or
617
623
* issue error messages.
618
624
*/
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 )
620
626
extends Application [Arg ](methRef, funType, args, resultType) {
621
627
type TypedArg = Arg
622
628
type Result = Unit
623
629
624
630
def applyKind = ApplyKind .Regular
625
631
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
627
633
case ref : TermRef if ref.denot.isOverloaded =>
628
634
// in this case we could not resolve overloading because no alternative
629
635
// matches expected type
@@ -633,8 +639,17 @@ trait Applications extends Compatibility {
633
639
case SAMType (sam) => argtpe <:< sam.toFunctionType(isJava = formal.classSymbol.is(JavaDefined ))
634
640
case _ => false
635
641
}
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
+ }
638
653
639
654
/** The type of the given argument */
640
655
protected def argType (arg : Arg , formal : Type ): Type
@@ -654,8 +669,8 @@ trait Applications extends Compatibility {
654
669
/** Subclass of Application for applicability tests with type arguments and value
655
670
* argument trees.
656
671
*/
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 ) {
659
674
def argType (arg : Tree , formal : Type ): Type =
660
675
if untpd.isContextualClosure(arg) && defn.isContextFunctionType(formal) then arg.tpe
661
676
else normalize(arg.tpe, formal)
@@ -665,18 +680,9 @@ trait Applications extends Compatibility {
665
680
def harmonizeArgs (args : List [Tree ]): List [Tree ] = harmonize(args)
666
681
}
667
682
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
-
677
683
/** 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 ) {
680
686
def argType (arg : Type , formal : Type ): Type = arg
681
687
def treeToArg (arg : Tree ): Type = arg.tpe
682
688
def isVarArg (arg : Type ): Boolean = arg.isRepeatedParam
@@ -1323,38 +1329,32 @@ trait Applications extends Compatibility {
1323
1329
/** Is given method reference applicable to argument trees `args`?
1324
1330
* @param resultType The expected result type of the application
1325
1331
*/
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 = {
1327
1333
def isApp (using Context ): Boolean =
1328
- new ApplicableToTrees (methRef, args, resultType).success
1334
+ new ApplicableToTrees (methRef, args, resultType, argMatch ).success
1329
1335
if (keepConstraint) isApp else explore(isApp)
1330
1336
}
1331
1337
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
-
1338
1338
/** Is given method reference applicable to argument types `args`?
1339
1339
* @param resultType The expected result type of the application
1340
1340
*/
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)
1343
1343
1344
1344
/** Is given type applicable to argument trees `args`, possibly after inserting an `apply`?
1345
1345
* @param resultType The expected result type of the application
1346
1346
*/
1347
1347
def isApplicableType (tp : Type , args : List [Tree ], resultType : Type , keepConstraint : Boolean )(using Context ): Boolean =
1348
1348
onMethod(tp, args.nonEmpty) {
1349
- isApplicableMethodRef(_, args, resultType, keepConstraint)
1349
+ isApplicableMethodRef(_, args, resultType, keepConstraint, ArgMatch . Compatible )
1350
1350
}
1351
1351
1352
1352
/** Is given type applicable to argument types `args`, possibly after inserting an `apply`?
1353
1353
* @param resultType The expected result type of the application
1354
1354
*/
1355
1355
def isApplicableType (tp : Type , args : List [Type ], resultType : Type )(using Context ): Boolean =
1356
1356
onMethod(tp, args.nonEmpty) {
1357
- isApplicableMethodRef(_, args, resultType)
1357
+ isApplicableMethodRef(_, args, resultType, ArgMatch . Compatible )
1358
1358
}
1359
1359
1360
1360
private def onMethod (tp : Type , followApply : Boolean )(p : TermRef => Boolean )(using Context ): Boolean = tp match {
@@ -1485,9 +1485,9 @@ trait Applications extends Compatibility {
1485
1485
|| {
1486
1486
if tp1.isVarArgsMethod then
1487
1487
tp2.isVarArgsMethod
1488
- && isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType )
1488
+ && isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType , ArgMatch . Compatible )
1489
1489
else
1490
- isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType )
1490
+ isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType , ArgMatch . Compatible )
1491
1491
}
1492
1492
case tp1 : PolyType => // (2)
1493
1493
inContext(ctx.fresh.setExploreTyperState()) {
@@ -1695,7 +1695,7 @@ trait Applications extends Compatibility {
1695
1695
*/
1696
1696
def adaptByResult (chosen : TermRef , alts : List [TermRef ]) = pt match {
1697
1697
case pt : FunProto if ! explore(resultConforms(chosen.symbol, chosen, pt.resultType)) =>
1698
- val conformingAlts = alts.filter (alt =>
1698
+ val conformingAlts = alts.filterConserve (alt =>
1699
1699
(alt ne chosen) && explore(resultConforms(alt.symbol, alt, pt.resultType)))
1700
1700
conformingAlts match {
1701
1701
case Nil => chosen
@@ -1796,7 +1796,7 @@ trait Applications extends Compatibility {
1796
1796
}
1797
1797
1798
1798
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 ))
1800
1800
1801
1801
/** Normalization steps before checking arguments:
1802
1802
*
@@ -1865,11 +1865,11 @@ trait Applications extends Compatibility {
1865
1865
1866
1866
def narrowByTrees (alts : List [TermRef ], args : List [Tree ], resultType : Type ): List [TermRef ] = {
1867
1867
val alts2 = alts.filterConserve(alt =>
1868
- isDirectlyApplicableMethodRef (alt, args, resultType)
1868
+ isApplicableMethodRef (alt, args, resultType, keepConstraint = false , ArgMatch . SubType )
1869
1869
)
1870
1870
if (alts2.isEmpty && ! ctx.isAfterTyper)
1871
1871
alts.filterConserve(alt =>
1872
- isApplicableMethodRef(alt, args, resultType, keepConstraint = false )
1872
+ isApplicableMethodRef(alt, args, resultType, keepConstraint = false , ArgMatch . CompatibleCAP )
1873
1873
)
1874
1874
else
1875
1875
alts2
@@ -1890,7 +1890,7 @@ trait Applications extends Compatibility {
1890
1890
narrowByTrees(alts2, pt.typedArgs(normArg(alts2, _, _)), resultType)
1891
1891
1892
1892
case pt @ PolyProto (targs1, pt1) =>
1893
- val alts1 = alts.filter (pt.canInstantiate)
1893
+ val alts1 = alts.filterConserve (pt.canInstantiate)
1894
1894
if isDetermined(alts1) then alts1
1895
1895
else
1896
1896
def withinBounds (alt : TermRef ) = alt.widen match
@@ -1904,7 +1904,7 @@ trait Applications extends Compatibility {
1904
1904
narrowByTypes(alts, args, resultType)
1905
1905
1906
1906
case pt =>
1907
- val compat = alts.filter (normalizedCompatible(_, pt, keepConstraint = false ))
1907
+ val compat = alts.filterConserve (normalizedCompatible(_, pt, keepConstraint = false ))
1908
1908
if (compat.isEmpty)
1909
1909
/*
1910
1910
* the case should not be moved to the enclosing match
@@ -1967,15 +1967,15 @@ trait Applications extends Compatibility {
1967
1967
skipParamClause(pt.typedArgs().tpes, Nil ), resType)
1968
1968
case _ =>
1969
1969
// prefer alternatives that need no eta expansion
1970
- val noCurried = alts.filter (! resultIsMethod(_))
1970
+ val noCurried = alts.filterConserve (! resultIsMethod(_))
1971
1971
val noCurriedCount = noCurried.length
1972
1972
if noCurriedCount == 1 then
1973
1973
noCurried
1974
1974
else if noCurriedCount > 1 && noCurriedCount < alts.length then
1975
1975
resolveOverloaded1(noCurried, pt)
1976
1976
else
1977
1977
// prefer alternatves that match without default parameters
1978
- val noDefaults = alts.filter (! _.symbol.hasDefaultParams)
1978
+ val noDefaults = alts.filterConserve (! _.symbol.hasDefaultParams)
1979
1979
val noDefaultsCount = noDefaults.length
1980
1980
if noDefaultsCount == 1 then
1981
1981
noDefaults
0 commit comments