Can we still generate bytecode when `inline def` method been called from Java

Motivation:
In Akka/Pekko there are some helper methods, if you marked it as inline def, it works very well in Scala 3, but will cause problem when call it from Java or old version where it was not marked inline def.

error] Test docs.javadsl.SqsPublishTest failed: java.lang.NoSuchMethodError: org.apache.pekko.util.FutureConverters$FutureOps$.asJava$extension(Lscala/concurrent/Future;)Ljava/util/concurrent/CompletionStage;, took 0.0 sec
[error]     at org.apache.pekko.http.javadsl.Http.shutdownAllConnectionPools(Http.scala:798)
[error]     at org.apache.pekko.stream.connectors.sqs.javadsl.BaseSqsTest.teardown(BaseSqsTest.java:62)

[1] chore: remove the inline modifier from pekko util. by He-Pin · Pull Request #1068 · apache/incubator-pekko · GitHub
[2] Unable to call Scala 3 inline methods from within Java · Issue #19346 · lampepfl/dotty · GitHub

I think I came up with a workaround to solve this which involves using the new Scala. 3 @targetName annotation, see Add targetName overloaded methods for Scala 3 inline methods by mdedetrich · Pull Request #1070 · apache/incubator-pekko · GitHub

This does bring up questions about whether its valid to combine both inline keyword with @targetName which would avoid needing to create a new method that would never be directly called in Scala (as the previously mentioned PR has to do), i.e.

@targetName("method")
inline def method()

It would be understandable if such a suggestion isn’t actionable for the same reasoning as Unable to call Scala 3 inline methods from within Java · Issue #19346 · lampepfl/dotty · GitHub

1 Like

Cool, in Kotlin there is a ‘@jvmName’ too°

1 Like

Instead of an alias you can create an abstract def in a superclass:

trait Base:
  def foo(x: Int): Int
class Sub extends Base:
  inline def foo(x: Int): Int = ...

This will generate bytecode for Sub#foo.

In general though I would recommend just not using inline for performance and letting the JVM perform inlining itself.

2 Likes

Thanks for the suggestion, we decided to revert the change and I don’t think the inheritence method would work in our case anyways since our implementation class extends AnyVal which disables any inheritance (iirc).

Im still wondering why the @targetName trick didn’t work, according to documentation it should have theoretically worked? You can look at the previously referenced PR but as far as I understand it should have created those original methods in the JVM bytecode which should have been picked up at runtime.

True, in our case we were using inline primarily because its getting rid of a cross compat wrapper class and also because it was a case of why not, i.e. free lunch