scala3 icon indicating copy to clipboard operation
scala3 copied to clipboard

private inline methods can't call abstract inline methods

Open felher opened this issue 1 year ago • 0 comments

Compiler version

3.3.1 (and all current RCs as far as I can tell)

Minimized code

trait SomeTrait:
  inline def base: Unit

  inline def doSomething: Unit = doSomethingHelper
  private inline def doSomethingHelper: Unit = base

object Impl extends SomeTrait:
  inline def base: Unit = ()

object Main:
  Impl.doSomething

Output

[error] -- Error: /tmp/test/src/main/scala/Main.scala:11:7 -----------------------------
[error] 11 |  Impl.doSomething
[error]    |  ^^^^^^^^^^^^^^^^
[error]    |  Deferred inline method base in trait SomeTrait cannot be invoked

Expectation

Should compile

Shallow Investigation

I didn't look into this deeply, but maybe the problem has to do with how the support for calling private inline methods is currently handled (see #15075). It works by remapping Select trees if they are private inline methods:

case tree @ Select(qual: This, name) if tree.symbol.is(Private) && tree.symbol.isInlineMethod =>
  // ... 
  cpy.Select(tree)(qual.asInstance(qual.tpe.widen), name)

which basically rewrites the code

inline def doSomething: Unit = doSomethingHelper

to

inline def doSomething: Unit = this.asInstanceOf[SomeTrait].doSomethingHelper

and I assume this leads the Inliner to select the abstract definition in SomeTrait later on, not the one on Impl. Of course, abstract inline methods can't be invoked directly, so when the compiler reaches private def inlineIfNeeded in Inliner.scala, both the Deferred and Inline flags are set and the above error is given.

felher avatar Feb 19 '24 23:02 felher