Встроенная функция не может получить доступ к непубличным API: @PublishedApi vs @Suppress vs @JvmSynthetic

В Kotlin, когда у меня есть непубличный член и inline fun которое его вызывает, возникает ошибка компиляции:

Ошибка: (22, 25). Kotlin: встроенная функция Public-API не может получить доступ к private fun f(): Unit не относящимся к публичному API. private fun f(): Unit определенная в com.example

Я нашел несколько способов назвать свою функцию внутри общедоступного inline fun , но что это лучший способ сделать это?

Предположим, что у меня есть private fun f() { } . Тогда параметры, которые я нашел, следующие:

  • fun f() { }

    Просто сделайте это общедоступным. Это базовое решение, но, если у остальных окажутся серьезные недостатки, это может оказаться лучшим.

  • @PublishedApi internal fun f() { }

    Представленный в Kotlin 1.1-M04 , аннотация может быть применена к внутреннему члену, что делает его эффективно публичным. Следствие, которое я заметил, это то, что любой пользователь библиотеки все равно сможет вызвать его из кода Java, вот что мне не нравится в этом.

  • @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") inline fun g() { f() }

    Найденный в источниках stdlib , эта аннотация, кажется, подавляет ошибку при применении к вызывающей функции. Но каковы его ограничения? Может ли он использоваться только для inline функций? Повреждает ли программа в некоторых случаях? Я попытался вызвать функцию non-inline из встроенного с этим трюком, и это сработало, но выглядит подозрительно.

  • @JvmSynthetic @PublishedApi internal fun f() { }

    Объедините второе решение с синтетическим флагом в байтекоде. Я не уверен, что это правильное использование @JvmSynthetic , но это, похоже, скрывает эту функцию от кода Java, что решает проблему @PublishedApi internal .

Итак, какое из этих решений является лучшим способом вызвать непубличную функцию из общедоступного встроенного? Каковы недостатки каждого решения, которое я не вижу?

@PublishedApi internal – это предполагаемый способ публикации непубличного API для использования в публичных встроенных функциях.

Этот @PublishedApi internal член @PublishedApi internal становится общедоступным, и его имя не искажается (если вы заметили обратное, напишите ошибку).

@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") является обходной способ обхода в отсутствие @PublisedApi основанный на подавлении ошибки и поэтому не рекомендуется. С введением @PublishedApi это подавление будет очищено от stdlib.

@JvmSynthetic сочетании с @PublishedApi – интересный подход, однако он может вызвать некоторые проблемы при отладке, хотя я не уверен.