Skip to content

AbstractMethodError using Scala 2 http4s library/withDottyCompat #10827

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
rparree opened this issue Dec 17, 2020 · 2 comments · Fixed by #11603
Closed

AbstractMethodError using Scala 2 http4s library/withDottyCompat #10827

rparree opened this issue Dec 17, 2020 · 2 comments · Fixed by #11603

Comments

@rparree
Copy link

rparree commented Dec 17, 2020

Hi,

I'm trying to create a small service using http4s (0.21) on Scala 3, using withDottyCompat
Using 3.0.0-M3 (same results with M2), [email protected]

A very much stripped down version is available here: https://github.com/rparree/http4s-dotty

When running i'm getting the following error:

Receiver class LivenessRoutes$$anon$1 does not define or inherit an implementation of the resolved method 'abstract void org$http4s$dsl$impl$Methods$_setter_$GET_$eq(org.http4s.Method$Semantics$Safe)' of interface org.http4s.dsl.impl.Methods.

See full stacktrace here: https://gist.github.com/rparree/e19d5ff29c885160c17c18ac5bdc017b#file-rte

After posting this on the http4s gitter channel, @rossabaker suggested that this could potentially be a withDottyCompat related problem.

@griggt
Copy link
Contributor

griggt commented Dec 17, 2020

Thanks for reporting. A small reproducer is:

// build.sbt
scalaVersion := "3.0.0-M3"
libraryDependencies += ("org.http4s" %% "http4s-dsl" % "0.21.13").withDottyCompat(scalaVersion.value)
// Main.scala
import org.http4s.dsl.Http4sDsl

trait F[x]

object Test {
  def main(args: Array[String]): Unit = {
    val dsl = new Http4sDsl[F] {}
  }
}
sbt> run
[info] compiling 1 Scala source to /tmp/i10827/target/scala-3.0.0-M3/classes ...
[info] done compiling
[info] running Test
[error] (run-main-0) java.lang.AbstractMethodError: Method Test$$anon$1.org$http4s$dsl$impl$Methods$_setter_$GET_$eq(Lorg/http4s/Method$Semantics$Safe;)V is abstract
[error] java.lang.AbstractMethodError: Method Test$$anon$1.org$http4s$dsl$impl$Methods$_setter_$GET_$eq(Lorg/http4s/Method$Semantics$Safe;)V is abstract
[error]         at Test$$anon$1.org$http4s$dsl$impl$Methods$_setter_$GET_$eq(Main.scala)
[error]         at org.http4s.dsl.impl.Methods.$init$(Methods.scala:12)
[error]         at Test$$anon$1.<init>(Main.scala:7)
[error]         at Test$.main(Main.scala:7)
[error]         at Test.main(Main.scala)
[error]         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error]         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error]         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error]         at java.lang.reflect.Method.invoke(Method.java:498)

I'm working on minimizing to a standalone example.

@griggt griggt changed the title RuntimeException (possible withDottyCompat problem?) AbstractMethodError using Scala 2 http4s library/withDottyCompat Dec 17, 2020
@griggt
Copy link
Contributor

griggt commented Dec 17, 2020

Standalone example:

First, a library compiled with Scala 2:

// build.sbt
scalaVersion := "2.13.4"
organization := "test.http4s"
name := "i10827"
version := "0.1.0-SNAPSHOT"
// Lib.scala
package test.http4s

class Method(name: String)

object Method {
  trait Safe
  trait PermitsBody extends Method

  type SafeMethodWithBody = Method with Safe with PermitsBody
  val GET: SafeMethodWithBody = new Method("GET") with Safe with PermitsBody
}

trait Methods {
  val GET: Method.GET.type = Method.GET
}

Then a test program consuming the library with Scala 3:

// build.sbt
scalaVersion := "3.0.0-M3"
libraryDependencies += ("test.http4s" %% "i10827" % "0.1.0-SNAPSHOT").withDottyCompat(scalaVersion.value)
// Main.scala
import test.http4s.Methods

object Test {
  def main(args: Array[String]): Unit = {
    val m = new Methods {}
  }
}
sbt:test> run
[info] compiling 1 Scala source to /src/dotty-issues/i10827/test/target/scala-3.0.0-M3/classes ...
[info] done compiling
[info] running Test
[error] (run-main-0) java.lang.AbstractMethodError: Test$$anon$1.test$http4s$Methods$_setter_$GET_$eq(Ltest/http4s/Method$Safe;)V
[error] java.lang.AbstractMethodError: Test$$anon$1.test$http4s$Methods$_setter_$GET_$eq(Ltest/http4s/Method$Safe;)V
[error]         at test.http4s.Methods.$init$(Lib.scala:14)
[error]         at Test$$anon$1.<init>(Main.scala:5)
[error]         at Test$.main(Main.scala:5)
[error]         at Test.main(Main.scala)
[error]         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error]         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error]         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error]         at java.lang.reflect.Method.invoke(Method.java:498)

The generated bytecode (from 3.0.0-M3):

Compiled from "Main.scala"
final class Test$$anon$1 implements test.http4s.Methods {
  private test.http4s.Method$PermitsBody GET;

  public Test$$anon$1();
    Code:
       0: aload_0
       1: invokespecial #20                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: invokestatic  #24                 // InterfaceMethod test/http4s/Methods.$init$:(Ltest/http4s/Methods;)V
       8: invokestatic  #29                 // Method scala/runtime/Statics.releaseFence:()V
      11: return

  public test.http4s.Method$PermitsBody GET();
    Code:
       0: aload_0
       1: getfield      #34                 // Field GET:Ltest/http4s/Method$PermitsBody;
       4: areturn

  public void test$http4s$Methods$_setter_$GET_$eq(test.http4s.Method$PermitsBody);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #34                 // Field GET:Ltest/http4s/Method$PermitsBody;
       5: return
}

compared to 2.13.4:

Compiled from "Main.scala"
public final class Test$$anon$1 implements test.http4s.Methods {
  private test.http4s.Method$Safe GET;

  public test.http4s.Method$Safe GET();
    Code:
       0: aload_0
       1: getfield      #22                 // Field GET:Ltest/http4s/Method$Safe;
       4: areturn

  public void test$http4s$Methods$_setter_$GET_$eq(test.http4s.Method$Safe);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #22                 // Field GET:Ltest/http4s/Method$Safe;
       5: return

  public Test$$anon$1();
    Code:
       0: aload_0
       1: invokespecial #31                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: invokestatic  #35                 // InterfaceMethod test/http4s/Methods.$init$:(Ltest/http4s/Methods;)V
       8: invokestatic  #40                 // Method scala/runtime/Statics.releaseFence:()V
      11: return
}

See also #4619

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.

3 participants