# "Members of private classes can-not be accessed from non-private inline functions" - why?

**URL:** <https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449>\
**Category:** Language Design\
**Created:** [February 5, 2016, 7:54pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449 "2016-02-05T19:54:28Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![CLX](https://avatars.discourse-cdn.com/v4/letter/c/b9bd4f/32.png) [@CLX](https://discuss.kotlinlang.org/u/CLX)\
**Post date:** [February 5, 2016, 7:54pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/1 "2016-02-05T19:54:28Z")

</div>

Hello,

I ran into this while trying to update to rc-1036. Example:

```
class Test {
    private class Extender: Base() {
        private fun doSomething() {
            doInline { "Test" }
        }
    }

    private abstract class Base {
        protected fun duplicate(s: String) = s + s

        protected inline fun doInline(block: () -> String): String {
            return duplicate(block())
        }
    }
}

```

Basically, it’s an inline function calling a non-inline helper function. Why was this changed to be forbidden? If I’m not mistaken, inlining would replace `doInline { "Test" }` by `duplicate("Test")`, which would be allowed.

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![abreslav](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/abreslav/32/8279_2.png) [@abreslav](https://discuss.kotlinlang.org/u/abreslav)\
**Post date:** [February 6, 2016, 10:39pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/2 "2016-02-06T22:39:06Z")

</div>

Since the code of your iniline function will be inlined in a different class, the private class Extender might be inaccessible there. To make it work, lift Extender’s visibility to protected

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [February 7, 2016, 1:01am UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/3 "2016-02-07T01:01:53Z")

</div>

> [@abreslav](#):
>
> To make it work, lift Extender’s visibility to protected

I doubt it would help.  
`Extender` is the class where the `doInline` is inlined to, and it’s not accessed inside the inline function. It’s the protected `duplicate` function of the private `Base` class is accessed, and since the `doInline` is also protected, it’s perfectly visible from the places where `doInline` could be inlined, namely the `Extender` class.

---

<div class="post-metadata">

**Author:** ![CLX](https://avatars.discourse-cdn.com/v4/letter/c/b9bd4f/32.png) [@CLX](https://discuss.kotlinlang.org/u/CLX)\
**Post date:** [February 7, 2016, 1:37am UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/4 "2016-02-07T01:37:56Z")

</div>

Yup, that’s what I mean. Unless I’m missing something here, any class that could access `doInline` would have to have access to `duplicate` as well, since they’re both protected. I don’t know how the visibility of the containing class could make any difference.

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [February 11, 2016, 2:46pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/5 "2016-02-11T14:46:34Z")

</div>

I’ve filed this as [KT-11014](https://youtrack.jetbrains.com/issue/KT-11014)

---

<div class="post-metadata">

**Author:** ![pdvrieze](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/pdvrieze/32/1882_2.png) [@pdvrieze](https://discuss.kotlinlang.org/u/pdvrieze)\
**Post date:** [March 16, 2016, 8:23pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/6 "2016-03-16T20:23:18Z")

</div>

While it is clear that at jvm level there is no inline function and the called functions must have the right visibility, it would be worthwhile to still hide the infrastructure functions, classes and objects from being explicitly referenced (you can use them, but not their names).

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [February 1, 2017, 6:26pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/7 "2017-02-01T18:26:35Z")

</div>

@CLX KT-11014 is fixed and in Kotlin 1.1 your example compiles without warnings.

---

<div class="post-metadata">

**Author:** ![teebird](https://avatars.discourse-cdn.com/v4/letter/t/a8b319/32.png) [@teebird](https://discuss.kotlinlang.org/u/teebird)\
**Post date:** [May 17, 2018, 5:05pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/8 "2018-05-17T17:05:14Z")

</div>

While this is compiling, it looks like it won’t actually run, and I have no idea why. In our code we have this:

```auto
protected inline fun <reified TError> call(call: Call<TBody>, event: BaseEvent<TBody, TError>? = null, sticky: Boolean = true, async: Boolean = true, noinline onCompletion: (NetworkResponseWrapper<TBody, TError>) -> Unit = {}) {
        this.call?.cancel()
        this.call = call
        if (async) {
            launch {
                _call(call, event, TError::class.java, onCompletion, sticky)
            }
        } else {
            _call(call, event, TError::class.java, onCompletion, sticky)
        }
    }

    /**
     * Not intended to be used directly see call
     */
    protected fun <TError> _call(call: Call<TBody>, event: BaseEvent<TBody, TError>?, type: Class<TError>, onSuccess: (NetworkResponseWrapper<TBody, TError>) -> Unit, sticky: Boolean) {
        val res = handleCall(call, type)
        if (event != null && !call.isCanceled) {
            event.response = res
            val sendSticky = hasSubscribersForEvent(event.javaClass) || sticky
            postEvent(event, sendSticky)
        }
        this.call = null
        onSuccess(res)
    }

```

For which call() is then called from a class extending base service. This works if they are in the same package, but does NOT work if they are in they are not, with the exception stating \_call() is not accessible to the extending class. Specifically,

```auto
05-17 12:03:02.670 23835-23963/com.heartmath.globalcoherencenetwork.internal.debug E/AndroidRuntime: FATAL EXCEPTION: ForkJoinPool.commonPool-worker-1
    Process: com.heartmath.globalcoherencenetwork.internal.debug, PID: 23835
    java.lang.IllegalAccessError: Method 'void com.heartmath.globalcoherencenetwork.data.BaseService._call(retrofit2.Call, com.heartmath.globalcoherencenetwork.model.event.BaseEvent, java.lang.Class, kotlin.jvm.functions.Function1, boolean)' is inaccessible to class 'com.heartmath.globalcoherencenetwork.data.service.LoginService$login$$inlined$call$1' (declaration of 'com.heartmath.globalcoherencenetwork.data.service.LoginService$login$$inlined$call$1' appears in base.apk)
        at com.heartmath.globalcoherencenetwork.data.service.LoginService$login$$inlined$call$1.doResume(BaseService.kt:22)
        at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54)
        at kotlinx.coroutines.experimental.DispatchTask.run(CoroutineDispatcher.kt:129)
        at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1412)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:285)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1152)
        at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1990)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1938)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:

```

I should mention that the login service does extend the BaseService

---

<div class="post-metadata">

**Author:** ![pdvrieze](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/pdvrieze/32/1882_2.png) [@pdvrieze](https://discuss.kotlinlang.org/u/pdvrieze)\
**Post date:** [May 17, 2018, 9:13pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/9 "2018-05-17T21:13:21Z")

</div>

On the JVM protection is enforced at runtime, not only in the compiler. As inline methods disappear into the calling code, this calling code must have the correct access.

In your case the launch block creates a closure for the async call. This closure is automatically generated but certainly not a child of the class defining \_call. As such protected access is not enough (it’s only for children). In normal cases synthetic accessors get generated to allow broader access in the/a language than allowed by the JVM. It seems that in this case the accessors that would make the non-inline version valid are either not invoked or not generated (inline functions are implemented through some nasty bytecode manipulation).

For this particular case, as the only use of inline is the TError class, I would write a non-inline version that takes a parameter for that class and which is called by the version with the reified type.

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [May 18, 2018, 6:35am UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/10 "2018-05-18T06:35:15Z")

</div>

This looks like a bug, the invocation of `_call` from the `launch` lambda should be prohibited here. Could you report it to the [tracker](http://kotl.in/issue)?

---

<div class="post-metadata">

**Author:** ![teebird](https://avatars.discourse-cdn.com/v4/letter/t/a8b319/32.png) [@teebird](https://discuss.kotlinlang.org/u/teebird)\
**Post date:** [May 18, 2018, 7:21pm UTC](https://discuss.kotlinlang.org/t/members-of-private-classes-can-not-be-accessed-from-non-private-inline-functions-why/1449/12 "2018-05-18T19:21:31Z")

</div>

I went to post it, but it seems that this is already posted under this issue: [https://youtrack.jetbrains.com/issue/KT-22625](https://youtrack.jetbrains.com/issue/KT-22625). The issue looks like it’s the simplest case example already, I don’t think it would necessarily be useful to add my case, but I can if you still think it’s useful.
