Skip to content

Commit 6cc5b49

Browse files
committed
Avoid overloading error involving SAM conversions
After the previous commit (and also in Scala 2), the following code doesn't compile: def foo[V](v: V): Int = 1 def foo[U](fn: java.util.function.Function[Int, U]): Int = 2 val f: Int => Int = x => x foo(f) // error: ambiguous overload The problem is that we assume that the overload taking a `Function` is applicable, even though it cannot be used since `f` is not a lambda expression. We can fix this by inspecting the shape of the argument and disallowing SAM conversion if the argument is known to be a non-lambda tree.
1 parent 0470bfc commit 6cc5b49

File tree

3 files changed

+13
-20
lines changed

3 files changed

+13
-20
lines changed

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ trait Applications extends Compatibility {
316316
abstract class Application[Arg](methRef: TermRef, funType: Type, args: List[Arg], resultType: Type)(using Context) {
317317

318318
/** The type of typed arguments: either tpd.Tree or Type */
319-
type TypedArg
319+
type TypedArg <: Tree | Type
320320

321321
/** The kind of application that gets typed */
322322
def applyKind: ApplyKind
@@ -621,7 +621,7 @@ trait Applications extends Compatibility {
621621
* in a "can/cannot apply" answer, without needing to construct trees or
622622
* issue error messages.
623623
*/
624-
abstract class TestApplication[Arg](methRef: TermRef, funType: Type, args: List[Arg], resultType: Type, argMatch: ArgMatch)(using Context)
624+
abstract class TestApplication[Arg <: Tree | Type](methRef: TermRef, funType: Type, args: List[Arg], resultType: Type, argMatch: ArgMatch)(using Context)
625625
extends Application[Arg](methRef, funType, args, resultType) {
626626
type TypedArg = Arg
627627
type Result = Unit
@@ -637,7 +637,15 @@ trait Applications extends Compatibility {
637637
val argtpe1 = argtpe.widen
638638

639639
def SAMargOK =
640-
defn.isFunctionType(argtpe1) && formal.match
640+
val isLambda = defn.isFunctionType(argtpe1) && arg.match
641+
case closure(_) =>
642+
true
643+
case arg: Tree =>
644+
// `arg` might be an untyped function due to how `FunProto#cacheTypedArg` works.
645+
untpd.isFunction(arg)
646+
case _: Type =>
647+
true
648+
isLambda && defn.isFunctionType(argtpe1) && formal.match
641649
case SAMType(sam) => argtpe <:< sam.toFunctionType(isJava = formal.classSymbol.is(JavaDefined))
642650
case _ => false
643651

tests/neg/i11938.scala

Lines changed: 0 additions & 16 deletions
This file was deleted.

tests/run/i11938.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ object Test {
99

1010
def main(args: Array[String]): Unit = {
1111
assert(foo((x: Int) => x) == 2)
12+
val f: Int => Int = x => x
13+
assert(foo(f) == 1)
1214
val jf: Function[Int, Int] = x => x
1315
assert(foo(jf) == 2)
1416

1517
assert(foo2(x => x) == 1)
16-
val f: Int => Int = x => x
1718
assert(foo2(f) == 1)
1819
assert(foo2({ case x if x % 2 == 0 => x }) == 2)
1920
val pf: PartialFunction[Int, Int] = { case x if x % 2 == 0 => x }

0 commit comments

Comments
 (0)