Skip to content

Different overloading rules in Scala 2 and 3 for SAMs #11938

Closed
@odersky

Description

@odersky

Related to #11899:

import java.util.function.Function

class Future[T](val initial: T) {
  //def map[V](v: V): Unit = println(v)
  //def map(s: String): Unit = println(s)
  def map[U](fn: Function[T, U]): Unit = println(fn(initial))
}

object Test {
  val f = new Future(42)
  val fn = (i: Int) => i.toString
  def main(args: Array[String]): Unit =
    f.map((i: Int) => i.toString)
}

If I compile and run this code with one version of map I get 42. But if I uncomment the first generic overload of map I get Test$$$Lambda$2/1705736037@12bc6874 in Scala 3. Scala 2 still prints 42.

The difference seems to be that SAM conversion is considered only in second rank for eligibility of overloading resolution. So Scala 3 picks the first overload, but Scala 2 picks the second. The problem in #11899 seems to be that Scala-2 thought it could do a SAM conversion when doing overloading resolution but ran into a type error later.

Interestingly, if the second overload of map for String is uncommented, but the first is left commented, both Scala 2 and 3 print 42. So Scala 3 does figure out it can do a SAM conversion if no other alternative is applicable.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions