Skip to content

Commit 1d62597

Browse files
committed
Change treatment of SAMs in overloading resolution
Always consider a function type A as conforming to a corresponding SAM type B, unless B is a subtype of A. The unless... part is so that `PartialFunction[A, B]` is seen as strictly better than `A => B`. This is an alternate fix for #11938 that does not treat FunctionalInterfaces specifically.
1 parent 649a6ac commit 1d62597

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,18 @@ trait Applications extends Compatibility {
629629

630630
def applyKind = ApplyKind.Regular
631631

632+
/** Is `tp1` a function type that can be converted by a SAM comversion to `tp2`,
633+
* and that is not at the same time a supertype of `tp2`?
634+
*/
635+
private def isSamCompatible(tp1: Type, tp2: Type)(using Context): Boolean =
636+
defn.isFunctionType(tp1)
637+
&& {
638+
tp2.match
639+
case SAMType(sam) => tp1 <:< sam.toFunctionType(isJava = tp2.classSymbol.is(JavaDefined))
640+
case _ => false
641+
}
642+
&& !(tp2 relaxed_<:< tp1)
643+
632644
protected def argOK(arg: TypedArg, formal: Type): Boolean = argType(arg, formal) match
633645
case ref: TermRef if ref.denot.isOverloaded =>
634646
// in this case we could not resolve overloading because no alternative
@@ -641,10 +653,11 @@ trait Applications extends Compatibility {
641653
case SAMType(sam) => argtpe <:< sam.toFunctionType(isJava = formal.classSymbol.is(JavaDefined))
642654
case _ => false
643655
if argMatch == ArgMatch.SubType then
644-
(argtpe relaxed_<:< formal.widenExpr) || SAMargOK(onlyFunctionalInterface = true)
656+
(argtpe relaxed_<:< formal.widenExpr)
657+
|| isSamCompatible(argtpe.widen, formal)
645658
else
646659
isCompatible(argtpe, formal)
647-
|| ctx.mode.is(Mode.ImplicitsEnabled) && SAMargOK(onlyFunctionalInterface = false)
660+
|| isSamCompatible(argtpe.widen, formal)
648661
|| argMatch == ArgMatch.CompatibleCAP
649662
&& {
650663
val argtpe1 = argtpe.widen

0 commit comments

Comments
 (0)