bug icon indicating copy to clipboard operation
bug copied to clipboard

SAM convert not work in overloaded method parameter.

Open counter2015 opened this issue 3 years ago • 5 comments

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

counter2015 avatar Mar 18 '22 11:03 counter2015

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"))

Jasper-M avatar Mar 18 '22 12:03 Jasper-M

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.

som-snytt avatar Mar 18 '22 13:03 som-snytt

The previous comment "subtype of an overload" ought to say "is more specific than another alternative".

I refuse.

Jasper-M avatar Mar 18 '22 13:03 Jasper-M

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

jxnu-liguobin avatar Mar 18 '22 15:03 jxnu-liguobin

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

SethTisue avatar Apr 19 '22 17:04 SethTisue