@@ -614,7 +614,6 @@ trait Applications extends Compatibility {
614
614
615
615
/** The degree to which an argument has to match a formal parameter */
616
616
enum ArgMatch :
617
- case SubType // argument is a relaxed subtype of formal
618
617
case Compatible // argument is compatible with formal
619
618
case CompatibleCAP // capture-converted argument is compatible with formal
620
619
@@ -635,21 +634,38 @@ trait Applications extends Compatibility {
635
634
// matches expected type
636
635
false
637
636
case argtpe =>
638
- def SAMargOK = formal match {
639
- case SAMType (sam) => argtpe <:< sam.toFunctionType(isJava = formal.classSymbol.is(JavaDefined ))
640
- case _ => false
641
- }
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
- }
637
+ val argtpe1 = argtpe.widen
638
+
639
+ def SAMargOK =
640
+ defn.isFunctionType(argtpe1) && formal.match
641
+ case SAMType (sam) => argtpe <:< sam.toFunctionType(isJava = formal.classSymbol.is(JavaDefined ))
642
+ case _ => false
643
+
644
+ isCompatible(argtpe, formal)
645
+ // Only allow SAM-conversion to PartialFunction if implicit conversions
646
+ // are enabled. This is necessary to avoid ambiguity between an overload
647
+ // taking a PartialFunction and one taking a Function1 because
648
+ // PartialFunction extends Function1 but Function1 is SAM-convertible to
649
+ // PartialFunction. Concretely, given:
650
+ //
651
+ // def foo(a: Int => Int): Unit = println("1")
652
+ // def foo(a: PartialFunction[Int, Int]): Unit = println("2")
653
+ //
654
+ // - `foo(x => x)` will print 1, because the PartialFunction overload
655
+ // won't be seen as applicable in the first call to
656
+ // `resolveOverloaded`, this behavior happens to match what Java does
657
+ // since PartialFunction is not a SAM type according to Java
658
+ // (`isDefined` is abstract).
659
+ // - `foo { case x if x % 2 == 0 => x }` will print 2, because both
660
+ // overloads are applicable, but PartialFunction is a subtype of
661
+ // Function1 so it's more specific.
662
+ || (! formal.isRef(defn.PartialFunctionClass ) || ctx.mode.is(Mode .ImplicitsEnabled )) && SAMargOK
663
+ || argMatch == ArgMatch .CompatibleCAP
664
+ && {
665
+ val argtpe1 = argtpe.widen
666
+ val captured = captureWildcards(argtpe1)
667
+ (captured ne argtpe1) && isCompatible(captured, formal.widenExpr)
668
+ }
653
669
654
670
/** The type of the given argument */
655
671
protected def argType (arg : Arg , formal : Type ): Type
@@ -1863,17 +1879,10 @@ trait Applications extends Compatibility {
1863
1879
else
1864
1880
alts
1865
1881
1866
- def narrowByTrees (alts : List [TermRef ], args : List [Tree ], resultType : Type ): List [TermRef ] = {
1867
- val alts2 = alts.filterConserve(alt =>
1868
- isApplicableMethodRef(alt, args, resultType, keepConstraint = false , ArgMatch .SubType )
1882
+ def narrowByTrees (alts : List [TermRef ], args : List [Tree ], resultType : Type ): List [TermRef ] =
1883
+ alts.filterConserve(alt =>
1884
+ isApplicableMethodRef(alt, args, resultType, keepConstraint = false , ArgMatch .CompatibleCAP )
1869
1885
)
1870
- if (alts2.isEmpty && ! ctx.isAfterTyper)
1871
- alts.filterConserve(alt =>
1872
- isApplicableMethodRef(alt, args, resultType, keepConstraint = false , ArgMatch .CompatibleCAP )
1873
- )
1874
- else
1875
- alts2
1876
- }
1877
1886
1878
1887
record(" resolveOverloaded.FunProto" , alts.length)
1879
1888
val alts1 = narrowBySize(alts)
0 commit comments