diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 452c6d197310..8a1db87a4f92 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -2123,34 +2123,27 @@ trait Applications extends Compatibility { else resolveMapped(alts1, _.widen.appliedTo(targs1.tpes), pt1) case pt => - val compat0 = pt.dealias match - case defn.FunctionNOf(args, resType, _) => - narrowByTypes(alts, args, resType) - case _ => - Nil - if (compat0.isEmpty) then - val compat = alts.filterConserve(normalizedCompatible(_, pt, keepConstraint = false)) - if (compat.isEmpty) - /* - * the case should not be moved to the enclosing match - * since SAM type must be considered only if there are no candidates - * For example, the second f should be chosen for the following code: - * def f(x: String): Unit = ??? - * def f: java.io.OutputStream = ??? - * new java.io.ObjectOutputStream(f) - */ - pt match { - case SAMType(mtp, _) => - narrowByTypes(alts, mtp.paramInfos, mtp.resultType) - case _ => - // pick any alternatives that are not methods since these might be convertible - // to the expected type, or be used as extension method arguments. - val convertible = alts.filterNot(alt => - normalize(alt, IgnoredProto(pt)).widenSingleton.isInstanceOf[MethodType]) - if convertible.length == 1 then convertible else compat - } - else compat - else compat0 + val compat = alts.filterConserve(normalizedCompatible(_, pt, keepConstraint = false)) + if compat.isEmpty then + pt match + case SAMType(mtp, _) => + // If we have a SAM type as expected type, treat it as if the expression was eta-expanded + // Note 1: No need to do that for function types, the previous normalizedCompatible test already + // handles those. + // Note 2: This case should not be moved to the enclosing match + // since fSAM types must be considered only if there are no candidates. + // For example, the second f should be chosen for the following code: + // def f(x: String): Unit = ??? + // def f: java.io.OutputStream = ??? + // new java.io.ObjectOutputStream(f) + narrowByTypes(alts, mtp.paramInfos, mtp.resultType) + case _ => + // pick any alternatives that are not methods since these might be convertible + // to the expected type, or be used as extension method arguments. + val convertible = alts.filterNot(alt => + normalize(alt, IgnoredProto(pt)).widenSingleton.isInstanceOf[MethodType]) + if convertible.length == 1 then convertible else compat + else compat } /** The type of alternative `alt` after instantiating its first parameter diff --git a/tests/run/i19641.scala b/tests/run/i19641.scala new file mode 100644 index 000000000000..3a3ef191aafc --- /dev/null +++ b/tests/run/i19641.scala @@ -0,0 +1,17 @@ +type DiagnosticConsturctor = (Int) => DiagnosticSet + +final class Diagnostic + +final class DiagnosticSet(elements: List[Diagnostic] = List()) + +enum Result: + case Success extends Result + case Failure(diagnose: DiagnosticConsturctor) extends Result + def diagnose(n: Int): DiagnosticSet = + this match + case Success => DiagnosticSet() + case Failure(d) => d(n) + +@main def Test(): Unit = + val r : Result = Result.Failure((n) => DiagnosticSet(List(Diagnostic()))) + r.diagnose(1) diff --git a/tests/run/i4364a.scala b/tests/run/i4364a.scala index 8bf62e545807..869e7dd6530e 100644 --- a/tests/run/i4364a.scala +++ b/tests/run/i4364a.scala @@ -6,8 +6,10 @@ object Test { def f(x: String): Unit = () def foo(c: Consumer[String]) = c.accept("") + def bar(c: String => Unit) = c("") def main(args: Array[String]) = { foo(f) + bar(f) } }