Skip to content

AbstractMethodError only if application code is in a module separate from library code #23245

Open
@swaldman

Description

@swaldman

Compiler version

3.3.6 and 3.7.0

Minimized code

The following code will compile, and its test (logadapter.test.Test) will run fine. (Try it as-is in scala-cli. There are no external dependencies.)

However, if the logadapter.test package is placed in a separate module, then compiled separately against the rest, a java.lang.AbstractMethodError results when the test program is run. (Try out this sbt project.)

package logadapter:

  trait AbstractLogAdapter:
    def info( message : String ) : Unit

  trait AbstractApi[T <: AbstractLogAdapter]:
    def logAdapterFor( loggerName : String ) : T
    trait SelfLogging:
      given adapter : T = logAdapterFor(this.getClass.getName)

  object Api extends logadapter.AbstractApi[LogAdapter]:
    def logAdapterFor( loggerName : String ) : LogAdapter = new LogAdapter( loggerName )

  class LogAdapter( loggerName : String ) extends logadapter.AbstractLogAdapter:
    def info( message : String ) : Unit = System.err.println( s"INFO [${loggerName}] ${message}" )

package logadapter.test:

  object Test extends logadapter.Api.SelfLogging:
    def main(args : Array[String]) : Unit =
      summon[logadapter.LogAdapter].info("Hello")

Output

When the (test) application code is compiled separately from the test code, something like the following results. (Line numbers will be off, since I've had to bring the test code into a separate file.)

java.lang.AbstractMethodError: Receiver class logadapter.test.Test$ does not define or inherit an implementation of the resolved method 'abstract logadapter.AbstractApi logadapter$AbstractApi$SelfLogging$$$outer()' of interface logadapter.AbstractApi$SelfLogging.
	at logadapter.AbstractApi$SelfLogging.adapter(core.scala:9)
	at logadapter.AbstractApi$SelfLogging.adapter$(core.scala:8)
	at logadapter.test.Test$.adapter$lzyINIT1(core.scala:3)
	at logadapter.test.Test$.adapter(core.scala:3)
	at logadapter.test.Test$.main(core.scala:5)
	at logadapter.test.Test.main(core.scala)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at sbt.Run.invokeMain(Run.scala:135)
	at sbt.Run.execute$1(Run.scala:85)
	at sbt.Run.$anonfun$runWithLoader$5(Run.scala:112)
	at sbt.Run$.executeSuccess(Run.scala:178)
	at sbt.Run.runWithLoader(Run.scala:112)
	at sbt.Defaults$.$anonfun$bgRunTask$6(Defaults.scala:2072)
	at sbt.Defaults$.$anonfun$termWrapper$2(Defaults.scala:2011)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
	at scala.util.Try$.apply(Try.scala:213)
	at sbt.internal.BackgroundThreadPool$BackgroundRunnable.run(DefaultBackgroundJobService.scala:378)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)

Expectation

Whether the test application is compiled separately or together with the "library" code, I expect the same output:

INFO [logadapter.test.Test$] Hello

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions