Accessing private declarations from inline functions

Sometimes, inline functions have more priveliges, than their callsite has.

class A {
    private fun bar() { println("bar")}
    inline internal fun foo() = bar()
}

fun main() {
    A().foo()
}

This code is compilable, and effectively equivalent to calling bar() in main. But bar() is a private function and can't be called in main().

Current non-jvm approach

As inlining happens after klib linking, there is no issue with that.

Current jvm-approach

For methods, synthetic accessors are generated. For example, class A from above is generated to

public final class A {
  public A();
  private final void bar();
  public final void foo$main();
  public static final void access$bar(A);
}

And this access$bar(A) method is called instead of bar inside inline functions.

Accessing classes is more complex. They are just accessed as is. Which works in simple cases, but for example

// other.kt
package other

class A {
    private class B public constructor() {
        fun bar() { println("bar")}
    }

    private fun produce() : Any = B()
    private fun consume(b: B) { b.bar() }
    inline internal fun foo() {
        val x = produce() as B
        consume(x)
    }
}
// main.kt
fun main() {
    other.A().foo()
}

fails with IllegalAccessError.

It is unclear if it should be considered as a bug, and deprecated, or it is intended behaviour.

Probably, we can use this approach in all backends and move it to fir2ir phase.