Skip to content

Proper SAM handling with method values of zero-parameter methods #284

Closed
@adamvoss

Description

@adamvoss

In 2.12, method value syntax cannot be used to assign a SAM convertible, zero-parameter method to a SAM type (NotOkay in code sample below). SAM conversion does not seem to occur yet implicit views are not utilized unless SAM conversion is explicitly suppressed (Ok2 below).

Based on the behavior of one-parameter (Ok1) and parameterless (Ok3) methods, it would seem that the correct behavior would be for SAM conversion to occur.

class Ok1 {
  trait Sam1 { def apply(x: Any): Unit }
  def render(x: Any) = {}
  val handler: Sam1 = render _ // sam conversion happens here
}

class Ok2 {
  implicit def conv(x: Function0[Unit]): Runnable = () => x()
  def render() = {}
  val handler: Runnable = (render _): Function0[Unit] // suppress sam conversion by typing the method value `render _` as a function-type, which will then expand to `() => render()` via eta-expansion, which will ultimately be converted via the implicit view `conv` to the expected type `Runnable`
}

class Ok3 {
  def render = {}
  val handler: Runnable = render _ // sam conversion happens here
}

class NotOkay1 {
  implicit def conv(x: Function0[Unit]): Runnable = () => x()
  def render() = {}
  val handler: Runnable = render _ // Fails, neither sam conversion or implicit view is applied
}

In 2.11, method value syntax worked fine for assigning zero-parameter methods to SAM convertible types when an implicit view was present.

Some initial discussion with Adriaan regarding if this is intentional scala/scala#4822 (comment) (tl;dr: behavior is iffy, probably should do sam conversion, file ticket here)

Motivating case: the impact on js.Function0 found when trying to upgrade the Hands-on Scala.js tutorial to 2.12. scala-js/scala-js#2656

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions