Skip to content

Commit 0eb2cf9

Browse files
ilmirusSpace Team
authored andcommitted
JVM: Do not implicitly expose functions with @JvmName annotation
if the functions return inline class. #KT-78358 #KT-78386 Fixed
1 parent 49c1bcc commit 0eb2cf9

File tree

6 files changed

+14
-42
lines changed

6 files changed

+14
-42
lines changed

compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ import org.jetbrains.kotlin.name.JvmStandardClassIds.JVM_SYNTHETIC_ANNOTATION_FQ
6161
import org.jetbrains.kotlin.name.Name
6262
import org.jetbrains.kotlin.psi.KtFile
6363
import org.jetbrains.kotlin.resolve.DescriptorUtils
64+
import org.jetbrains.kotlin.resolve.JVM_NAME_ANNOTATION_FQ_NAME
6465
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
6566
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
6667
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
@@ -249,23 +250,30 @@ val IrDeclaration.isStaticMultiFieldValueClassReplacement: Boolean
249250
|| origin == JvmLoweredDeclarationOrigin.STATIC_MULTI_FIELD_VALUE_CLASS_CONSTRUCTOR
250251

251252
fun IrDeclaration.shouldBeExposedByAnnotationOrFlag(languageVersionSettings: LanguageVersionSettings): Boolean {
252-
if (!isFunctionWhichCanBeExposed()) return false
253+
val isPropagatedOrImplicit = propagatedOrImplicitJvmExposeBoxed(languageVersionSettings)
254+
val isExplicit = hasAnnotation(JVM_EXPOSE_BOXED_ANNOTATION_FQ_NAME)
255+
256+
if (!(isExplicit || isPropagatedOrImplicit)) return false
257+
if (!isFunctionWhichCanBeExposed(isPropagatedOrImplicit && !isExplicit)) return false
253258
if (hasAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME)) return false
254259

255-
return getAnnotation(JVM_EXPOSE_BOXED_ANNOTATION_FQ_NAME) != null ||
256-
parentClassOrNull?.getAnnotation(JVM_EXPOSE_BOXED_ANNOTATION_FQ_NAME) != null ||
257-
languageVersionSettings.supportsFeature(LanguageFeature.ImplicitJvmExposeBoxed)
260+
return true
258261
}
259262

263+
private fun IrDeclaration.propagatedOrImplicitJvmExposeBoxed(languageVersionSettings: LanguageVersionSettings): Boolean =
264+
parentClassOrNull?.getAnnotation(JVM_EXPOSE_BOXED_ANNOTATION_FQ_NAME) != null ||
265+
languageVersionSettings.supportsFeature(LanguageFeature.ImplicitJvmExposeBoxed)
266+
260267
// Do not duplicate function without inline classes in parameters, since it would lead to CONFLICTING_JVM_DECLARATIONS
261-
private fun IrDeclaration.isFunctionWhichCanBeExposed(): Boolean {
268+
private fun IrDeclaration.isFunctionWhichCanBeExposed(isPropagatedOrImplicit: Boolean): Boolean {
262269
if (this !is IrFunction || origin == IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER) return false
263270
// No sense in exposing suspend functions - they cannot be called from Java in normal way anyway
264271
if (isSuspend) return false
265272
// Cannot expose open or abstract - @JvmName problem
266273
if (isOverridable) return false
267274
if (parameters.any { it.type.isInlineClassType() }) return true
268-
if (!returnType.isInlineClassType()) return false
275+
// If the function is annotated with @JvmName, it is unmangled, so, we cannot implicitly expose it.
276+
if (!returnType.isInlineClassType() || (isPropagatedOrImplicit && hasAnnotation(JVM_NAME_ANNOTATION_FQ_NAME))) return false
269277
// It is not explicitly annotated, global and returns inline class, do not expose it, since otherwise
270278
// it would lead to ambiguous call on Java side
271279
// WARNING: Do not use parentAsClass here, otherwise, it leads to ICE in some obscure cases, see KT-78551

compiler/testData/asJava/lightClasses/lightClassByPsi/jvmExposeBoxed/directive/methodReturnWithJvmName.lib.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
public final class Foo /* Foo*/ {
2-
@kotlin.jvm.JvmExposeBoxed(jvmName = "foo")
3-
@org.jetbrains.annotations.NotNull()
4-
public final StringWrapper foo();// foo()
5-
62
@kotlin.jvm.JvmName(name = "foo")
73
@org.jetbrains.annotations.NotNull()
84
public final java.lang.String foo();// foo()

compiler/testData/asJava/lightClasses/lightClassByPsi/jvmExposeBoxed/featureInteraction/jvmNameVariable.lib.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
11
public final class Foo /* Foo*/ {
2-
@kotlin.jvm.JvmExposeBoxed(jvmName = "foo11")
3-
@org.jetbrains.annotations.NotNull()
4-
public final StringWrapper foo11();// foo11()
5-
6-
@kotlin.jvm.JvmExposeBoxed(jvmName = "foo41")
7-
@org.jetbrains.annotations.NotNull()
8-
public final StringWrapper foo41(int);// foo41(int)
9-
102
@kotlin.jvm.JvmExposeBoxed(jvmName = "fooGetter22")
113
@org.jetbrains.annotations.NotNull()
124
public final StringWrapper fooGetter22();// fooGetter22()

compiler/testData/asJava/lightClasses/lightClassByPsi/jvmExposeBoxed/featureInteraction/jvmNameVariableDirective.lib.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
11
public final class Foo /* Foo*/ {
2-
@kotlin.jvm.JvmExposeBoxed(jvmName = "foo11")
3-
@org.jetbrains.annotations.NotNull()
4-
public final StringWrapper foo11();// foo11()
5-
6-
@kotlin.jvm.JvmExposeBoxed(jvmName = "foo41")
7-
@org.jetbrains.annotations.NotNull()
8-
public final StringWrapper foo41(int);// foo41(int)
9-
102
@kotlin.jvm.JvmExposeBoxed(jvmName = "fooGetter22")
113
@org.jetbrains.annotations.NotNull()
124
public final StringWrapper fooGetter22();// fooGetter22()

compiler/testData/asJava/lightClasses/lightClassByPsi/jvmExposeBoxed/featureInteraction/jvmOverloadsReturnTypeJvmNameDirective.lib.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,4 @@
11
public final class Baz /* Baz*/ {
2-
@kotlin.jvm.JvmExposeBoxed(jvmName = "jvmMemberLevel")
3-
@kotlin.jvm.JvmOverloads()
4-
@org.jetbrains.annotations.NotNull()
5-
public final IntWrapper jvmMemberLevel();// jvmMemberLevel()
6-
7-
@kotlin.jvm.JvmExposeBoxed(jvmName = "jvmMemberLevel")
8-
@kotlin.jvm.JvmOverloads()
9-
@org.jetbrains.annotations.NotNull()
10-
public final IntWrapper jvmMemberLevel(int);// jvmMemberLevel(int)
11-
12-
@kotlin.jvm.JvmExposeBoxed(jvmName = "jvmMemberLevel")
13-
@kotlin.jvm.JvmOverloads()
14-
@org.jetbrains.annotations.NotNull()
15-
public final IntWrapper jvmMemberLevel(int, int);// jvmMemberLevel(int, int)
16-
172
@kotlin.jvm.JvmName(name = "jvmMemberLevel")
183
@kotlin.jvm.JvmOverloads()
194
public final int jvmMemberLevel();// jvmMemberLevel()

compiler/testData/codegen/box/inlineClasses/jvmExposeBoxed/directive/methodReturnWithJvmName.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ public final class BoxKt {
88
public final class Foo {
99
// source: 'IC.kt'
1010
public method <init>(): void
11-
public final @kotlin.jvm.JvmExposeBoxed(jvmName="foo") @org.jetbrains.annotations.NotNull method foo(): StringWrapper
1211
public final @kotlin.jvm.JvmName(name="foo") @org.jetbrains.annotations.NotNull method foo(): java.lang.String
1312
}
1413

0 commit comments

Comments
 (0)