bug
bug copied to clipboard
SAM convert not work in overloaded method parameter.
Reproduction steps
Scala Version: 2.13.8
I cant reproduce it by raw scala, it's only reproduce in akka function.
I'm not sure if the bug is also related to akka.
Add akka library in sbt
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.5.32"
And then compile following code
import akka.actor.ActorSystem
import scala.concurrent.duration._
object BugExample {
def main(args: Array[String]): Unit = {
val system = ActorSystem("test")
implicit val ec = system.dispatcher
system.scheduler.schedule(1.second, 10.seconds, () => println("why cant convert this to Runnable"))
}
}
And here is the schedule method
def schedule(initialDelay: FiniteDuration, interval: FiniteDuration, runnable: Runnable)(
implicit executor: ExecutionContext): Cancellable
Compile failed with error
BugExample.scala:11:56: type mismatch;
[error] found : () => Unit
[error] required: Runnable
[error] system.scheduler.schedule(1.second, 10.seconds, () => println("why cant convert this to Runnable"))
Problem
Following code works well
import akka.actor.ActorSystem
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
object BugExample {
// self defined function works well
def test1() = {
def schedule(initialDelay: FiniteDuration, interval: FiniteDuration, runnable: Runnable)(
implicit executor: ExecutionContext): Unit = {
println(s"$initialDelay $interval")
runnable.run()
}
val system = ActorSystem("test")
implicit val ec = system.dispatcher
schedule(1.second, 10.seconds, () => println("works well 1"))
}
// declare type explicitly works well
def test2() = {
val system = ActorSystem("test")
implicit val ec = system.dispatcher
val f: Runnable = () => println("works well 2")
system.scheduler.schedule(1.second, 10.seconds, f)
}
def main(args: Array[String]): Unit = {
test1()
test2()
}
}
IMO, the compiler should convert () => scala.Unit to Runnable .
What's the problem here ?
Environment:
sbt: 1.6.2 jdk: corretto 17, openjdk 11
schedule is an overloaded method, with one overload being a subtype of another overload.
object X {
def schedule(x: Duration, f: Runnable) = 1
def schedule(x: FiniteDuration, f: Runnable) = 2
}
X.schedule(3.seconds, () => println("doesn't work"))
The previous comment "subtype of an overload" ought to say "is more specific than another alternative".
scala> import concurrent._, duration._
import concurrent._
import duration._
scala> object X {
| def schedule(x: Duration, f: Runnable) = 1
| def schedule(x: FiniteDuration, f: Runnable) = 2
| }
object X
scala>
scala> X.schedule(3.seconds, () => println("doesn't work"))
^
error: type mismatch;
found : () => Unit
required: Runnable
scala> def g(f: Runnable) = 42
def g(f: Runnable): Int
scala> g(() => println("it's a runnable"))
val res1: Int = 42
I don't know why that is a problem, but unrelatedly I hope github offers a feature to ensure that snippets compile, as in scaladoc. That would amaze me.
The previous comment "subtype of an overload" ought to say "is more specific than another alternative".
I refuse.
I investigated for a while. It seems that this is caused by overloading, but the specific reason is not clear and I'm still a novice. Seems to be here? https://github.com/scala/scala/blob/933b3c616b56ad1ab15be365121b7bc3ffa98b66/src/reflect/scala/reflect/internal/Types.scala#L1212
has anyone gone digging for past tickets on the interactions between SAM conversion and overloading? I feel like that's a feature intersection that has come up before, perhaps repeatedly