Skip to content

Lambda syntax for SAM crashes with AbstractMethodError #10068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sideeffffect opened this issue Oct 22, 2020 · 3 comments · Fixed by #11839
Closed

Lambda syntax for SAM crashes with AbstractMethodError #10068

sideeffffect opened this issue Oct 22, 2020 · 3 comments · Fixed by #11839

Comments

@sideeffffect
Copy link
Contributor

sideeffffect commented Oct 22, 2020

When using the Lambda syntax for SAM type, a trait in this case, the Dotty-compiled program crashes at runtime with java.lang.AbstractMethodError

Minimized code

def make[A](ord: (A, A) => Ordering): Ord[A] =
     (l, r) => ord(l, r) 

Output

Dotty compiles the code without a complaint, but the code crashes at runtime.

[info]       java.lang.AbstractMethodError: Method zio/prelude/Ord$$$Lambda$10282.checkCompare(Ljava/lang/Object;Ljava/lang/Object;)Lzio/prelude/PartialOrdering; is abstract
[info]       	at zio.prelude.Ord$$$Lambda$10282/1407254277.checkCompare(Unknown Source)
[info]       	at zio.prelude.PartialOrd.compare(PartialOrd.scala:21)

https://app.circleci.com/pipelines/github/zio/zio-prelude/741/workflows/53a57041-ca7f-442c-bd00-64fdf7c8a139/jobs/4226/steps

Expectation

Code should either fail to compile, or not crash. The same code works OK with Scala 2.

Workaround

Use the verbose way:

   def make[A](ord: (A, A) => Ordering): Ord[A] = new Ord[A] { 
    override protected def checkCompare(l: A, r: A): Ordering = ord(l, r)
  }

zio/zio-prelude@c0450bb
Then everything works as expected.

@sideeffffect sideeffffect changed the title Lambda syntex for SAM crashes with AbstractMethodError Lambda syntax for SAM crashes with AbstractMethodError Oct 22, 2020
@griggt
Copy link
Contributor

griggt commented Oct 24, 2020

Self-contained example:

sealed trait Partial
sealed trait Total extends Partial

case object Foo extends Total

trait P[A] {
  def bar(a: A): Partial
}

trait T[A] extends P[A] {
  def bar(a: A): Total
}

object T {
  def make[A](x: Total): T[A] =
    a => x

  // This alternate definition of `make` avoids the AbstractMethodError
  // def make[A](x: Total): T[A] = new T[A] {
  //   override def bar(a: A): Total = x
  // }
}

object Test {
  def total[A](a: A)(ev: T[A]): Total = ev.bar(a)
  def partial[A](a: A)(ev: P[A]): Partial = ev.bar(a)

  def go[A](a: A)(ev: T[A]): Unit = {
    println(a)
    println(total(a)(ev))     // OK
    println(partial(a)(ev))   // AbstractMethodError
  }

  def main(args: Array[String]): Unit =
    go(42)(T.make(Foo))
}

// Expected output:
// 42
// Foo
// Foo

Output with Dotty 3.0.0-M1-bin-20201022-b26dbc4-NIGHTLY:

sbt:i10068> run
[info] Compiling 1 Scala source to /src/dotty-issues/i10068/target/scala-3.0.0-M1/classes ...
[info] Done compiling.
[info] running Test
42
Foo
[error] (run-main-1b) java.lang.AbstractMethodError: T$$$Lambda$30563/710453870.bar(Ljava/lang/Object;)LPartial;
[error] java.lang.AbstractMethodError: T$$$Lambda$30563/710453870.bar(Ljava/lang/Object;)LPartial;
[error]         at Test$.partial(i10068.scala:26)
[error]         at Test$.go(i10068.scala:31)
[error]         at Test$.main(i10068.scala:35)
[error]         at Test.main(i10068.scala)

The covariant return type of bar seems to be necessary to trigger the AbstractMethodError.

This example runs without error on Scala 2.13.x and 2.12.n | n >= 5.

It fails at runtime with the AbstractMethodError on Dotty and Scala 2.12.n | n <= 4 (unless -Ydelambdafy:inline is given)

@michelou
Copy link
Contributor

@griggt Thanks for the nice and concise description.

@griggt
Copy link
Contributor

griggt commented Oct 24, 2020

Relevant fix from Scala 2.12.5: scala/scala#6087

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants