Skip to content

Commit 251514b

Browse files
Medowhillodersky
authored andcommitted
Fix #4364: Try SAM type when no candidates found
1 parent 615fdc9 commit 251514b

File tree

5 files changed

+50
-2
lines changed

5 files changed

+50
-2
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,8 @@ class Definitions {
816816
def SetterMetaAnnot(implicit ctx: Context): ClassSymbol = SetterMetaAnnotType.symbol.asClass
817817
lazy val ShowAsInfixAnotType: TypeRef = ctx.requiredClassRef("scala.annotation.showAsInfix")
818818
def ShowAsInfixAnnot(implicit ctx: Context): ClassSymbol = ShowAsInfixAnotType.symbol.asClass
819+
lazy val FunctionalInterfaceAnnotType = ctx.requiredClassRef("java.lang.FunctionalInterface")
820+
def FunctionalInterfaceAnnot(implicit ctx: Context) = FunctionalInterfaceAnnotType.symbol.asClass
819821

820822
// convenient one-parameter method types
821823
def methOfAny(tp: Type): MethodType = MethodType(List(AnyType), tp)

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1517,7 +1517,17 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
15171517
narrowByTypes(alts, args, resultType)
15181518

15191519
case pt =>
1520-
alts filter (normalizedCompatible(_, pt))
1520+
val noSam = alts filter (normalizedCompatible(_, pt))
1521+
if (noSam.isEmpty) {
1522+
pt match {
1523+
case SAMType(mtp) =>
1524+
val sam = narrowByTypes(alts, mtp.paramInfos, mtp.resultType)
1525+
if (sam.nonEmpty && !pt.classSymbol.hasAnnotation(defn.FunctionalInterfaceAnnot))
1526+
ctx.warning(ex"$pt does not have the @FunctionalInterface annotation.", ctx.tree.pos)
1527+
sam
1528+
case _ => noSam
1529+
}
1530+
} else noSam
15211531
}
15221532
val found = narrowMostSpecific(candidates)
15231533
if (found.length <= 1) found

tests/neg/i2033.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import collection._
33
object Test {
44
def check(obj: AnyRef): Unit = {
55
val bos = new ByteArrayOutputStream()
6-
val out = new ObjectOutputStream(println) // error
6+
val out = new ObjectOutputStream(println)
77
val arr = bos toByteArray ()
88
val in = (())
99
val deser = ()

tests/run/i4364a.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object Test {
2+
var flag = false
3+
4+
def f(): Unit = assert(false)
5+
def f(x: Int): Unit = assert(false)
6+
def f(x: String): Unit = flag = true
7+
8+
def foo(c: java.util.function.Consumer[String]) = c.accept("")
9+
10+
def main(args: Array[String]) = {
11+
foo(f)
12+
}
13+
}

tests/run/i4364b.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
object Test {
2+
var flag = false
3+
4+
def f(x: Int): Unit = assert(false)
5+
def f(x: String): Unit = assert(false)
6+
def f: java.io.OutputStream = new java.io.OutputStream {
7+
def write(x: Int) = ()
8+
}
9+
10+
def g(x: Int): Unit = flag = true
11+
def g(x: String): Unit = assert(false)
12+
13+
def main(args: Array[String]) = {
14+
val oosF = new java.io.ObjectOutputStream(f)
15+
oosF.write(0)
16+
oosF.close()
17+
18+
val oosG = new java.io.ObjectOutputStream(g) // need warning
19+
oosG.write(0)
20+
oosG.close()
21+
assert(flag)
22+
}
23+
}

0 commit comments

Comments
 (0)