@@ -614,7 +614,6 @@ trait Applications extends Compatibility {
614614
615615 /** The degree to which an argument has to match a formal parameter */
616616 enum ArgMatch :
617- case SubType // argument is a relaxed subtype of formal
618617 case Compatible // argument is compatible with formal
619618 case CompatibleCAP // capture-converted argument is compatible with formal
620619
@@ -635,21 +634,38 @@ trait Applications extends Compatibility {
635634 // matches expected type
636635 false
637636 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+ }
653669
654670 /** The type of the given argument */
655671 protected def argType (arg : Arg , formal : Type ): Type
@@ -1863,17 +1879,10 @@ trait Applications extends Compatibility {
18631879 else
18641880 alts
18651881
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 )
18691885 )
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- }
18771886
18781887 record(" resolveOverloaded.FunProto" , alts.length)
18791888 val alts1 = narrowBySize(alts)
0 commit comments