Skip to content

Commit 7c12968

Browse files
Backport "Drop special treatment of function types in overloading resolution" to LTS (#20914)
Backports #19654 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents 8b60f10 + 748c5c5 commit 7c12968

File tree

3 files changed

+40
-28
lines changed

3 files changed

+40
-28
lines changed

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

+21-28
Original file line numberDiff line numberDiff line change
@@ -2068,34 +2068,27 @@ trait Applications extends Compatibility {
20682068
else resolveMapped(alts1, _.widen.appliedTo(targs1.tpes), pt1)
20692069

20702070
case pt =>
2071-
val compat0 = pt.dealias match
2072-
case defn.FunctionNOf(args, resType, _) =>
2073-
narrowByTypes(alts, args, resType)
2074-
case _ =>
2075-
Nil
2076-
if (compat0.isEmpty) then
2077-
val compat = alts.filterConserve(normalizedCompatible(_, pt, keepConstraint = false))
2078-
if (compat.isEmpty)
2079-
/*
2080-
* the case should not be moved to the enclosing match
2081-
* since SAM type must be considered only if there are no candidates
2082-
* For example, the second f should be chosen for the following code:
2083-
* def f(x: String): Unit = ???
2084-
* def f: java.io.OutputStream = ???
2085-
* new java.io.ObjectOutputStream(f)
2086-
*/
2087-
pt match {
2088-
case SAMType(mtp, _) =>
2089-
narrowByTypes(alts, mtp.paramInfos, mtp.resultType)
2090-
case _ =>
2091-
// pick any alternatives that are not methods since these might be convertible
2092-
// to the expected type, or be used as extension method arguments.
2093-
val convertible = alts.filterNot(alt =>
2094-
normalize(alt, IgnoredProto(pt)).widenSingleton.isInstanceOf[MethodType])
2095-
if convertible.length == 1 then convertible else compat
2096-
}
2097-
else compat
2098-
else compat0
2071+
val compat = alts.filterConserve(normalizedCompatible(_, pt, keepConstraint = false))
2072+
if compat.isEmpty then
2073+
pt match
2074+
case SAMType(mtp, _) =>
2075+
// If we have a SAM type as expected type, treat it as if the expression was eta-expanded
2076+
// Note 1: No need to do that for function types, the previous normalizedCompatible test already
2077+
// handles those.
2078+
// Note 2: This case should not be moved to the enclosing match
2079+
// since fSAM types must be considered only if there are no candidates.
2080+
// For example, the second f should be chosen for the following code:
2081+
// def f(x: String): Unit = ???
2082+
// def f: java.io.OutputStream = ???
2083+
// new java.io.ObjectOutputStream(f)
2084+
narrowByTypes(alts, mtp.paramInfos, mtp.resultType)
2085+
case _ =>
2086+
// pick any alternatives that are not methods since these might be convertible
2087+
// to the expected type, or be used as extension method arguments.
2088+
val convertible = alts.filterNot(alt =>
2089+
normalize(alt, IgnoredProto(pt)).widenSingleton.isInstanceOf[MethodType])
2090+
if convertible.length == 1 then convertible else compat
2091+
else compat
20992092
}
21002093

21012094
/** The type of alternative `alt` after instantiating its first parameter

tests/run/i19641.scala

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
type DiagnosticConsturctor = (Int) => DiagnosticSet
2+
3+
final class Diagnostic
4+
5+
final class DiagnosticSet(elements: List[Diagnostic] = List())
6+
7+
enum Result:
8+
case Success extends Result
9+
case Failure(diagnose: DiagnosticConsturctor) extends Result
10+
def diagnose(n: Int): DiagnosticSet =
11+
this match
12+
case Success => DiagnosticSet()
13+
case Failure(d) => d(n)
14+
15+
@main def Test(): Unit =
16+
val r : Result = Result.Failure((n) => DiagnosticSet(List(Diagnostic())))
17+
r.diagnose(1)

tests/run/i4364a.scala

+2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ object Test {
66
def f(x: String): Unit = ()
77

88
def foo(c: Consumer[String]) = c.accept("")
9+
def bar(c: String => Unit) = c("")
910

1011
def main(args: Array[String]) = {
1112
foo(f)
13+
bar(f)
1214
}
1315
}

0 commit comments

Comments
 (0)