Scala 2.12/2.13 inliner is too aggressive?

In Pekko I am currently exploring in enabling the Scala 2.12/Scala 2.13 inliner, see Enable inliner for Scala 2 by mdedetrich · Pull Request #305 · apache/incubator-pekko · GitHub.

The problem I am hitting is that the inliner appears to be too aggressive, or put differently is if a method is annotated with @inline, rather than shortcircuting when it can it appears to be to continue to aggressively inline until it errors out.

For example with this method incubator-pekko/ByteIterator.scala at e6311a207672773c4b0a65a1711267e86777583e · apache/incubator-pekko · GitHub , i.e.

@inline private def current: ByteArrayIterator = iterators.head

The inline optimizer then complains with

[error] /Users/mdedetrich/github/incubator-pekko/actor/src/main/scala-2.13/org/apache/pekko/util/ByteIterator.scala:370:50: org/apache/pekko/util/ByteIterator$MultiByteArrayIterator::org$apache$pekko$util$ByteIterator$MultiByteArrayIterator$$current()Lorg/apache/pekko/util/ByteIterator$ByteArrayIterator; is annotated @inline but could not be inlined:
[error] Failed to check if org/apache/pekko/util/ByteIterator$MultiByteArrayIterator::org$apache$pekko$util$ByteIterator$MultiByteArrayIterator$$current()Lorg/apache/pekko/util/ByteIterator$ByteArrayIterator; can be safely inlined to org/apache/pekko/util/ByteIterator$MultiByteArrayIterator without causing an IllegalAccessError. Checking instruction INVOKEINTERFACE scala/collection/LinearSeq.head ()Ljava/lang/Object; (itf) failed:
[error] The method head()Ljava/lang/Object; could not be found in the class scala/collection/LinearSeq or any of its parents.
[error]       getToArray(xs, offset, n, 1) { getByte } { current.getBytes(_, _, _) }

so what appears to be occurring here is its inlining the current to iterators.head but then the inliner continues on further and is now trying to inline the head call itself which is whats causing it to go into the standard scala collections?

In case its not clear, the intention is for current to be inlined to iterators.head but not any further. I also tried to use "-opt-inline-from:org.apache.pekko.**,!scala.collection.**" in an attempt to get the Scala inliner to ignore anything from scala.collection package but it doesn’t seem to work as intended.

I don’t think so, the message says

Failed to check if MultiByteArrayIterator.current can be safely inlined to MultiByteArrayIterator, because
checking instruction INVOKEINTERFACE LinearSeq.head failed, because
the method head could not be found in the class LinearSeq or any of its parents

Might be a bug in the optimizer, I guess looking up method head in LinearSeq should work.

I looked into this harder and indeed you are right, it doesn’t appear to transitively look up head via the inheritance hierarchy. Should I file a bug on GitHub - scala/bug: Scala 2 bug reports only. Please, no questions — proper bug reports only.?

Sure, ideally with a self-contained reproducer :slight_smile:

1 Like

Will do, I will file the report now and mention there that I will try and create a minimized example. I also just noticed that it only appears to occur on Scala 2.13, Scala 2.12 seems to work fine.

1 Like

Bug report created at Scala 2.13 inline optimizer unable to correctly look up `.head` method in `scala.collection.LinearSeq` · Issue #12787 · scala/bug · GitHub, will try and get around to minimizing it in the next few days

1 Like

That’s more likely due to the changes in the 2.13 collections architecture, rather than changes in the optimizer.

1 Like

Created at GitHub - mdedetrich/scala-213-collections-inliner-bug: Scala 213 Collections Inliner Bug, turned out to be a lot easier then expected.

1 Like