diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmCachedDeclarations.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmCachedDeclarations.kt index fae7bffee0b..9589a5a8940 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmCachedDeclarations.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmCachedDeclarations.kt @@ -107,18 +107,18 @@ class JvmCachedDeclarations( if (jvmStaticFunction.isExternal) { // We move external functions to the enclosing class and potentially add accessors there. // The JVM backend also adds accessors in the companion object, but these are superfluous. - // TODO: this should really do the same as `makeProxy`, but without a body; otherwise, external - // functions in interface companions won't work (KT-43696). val staticExternal = context.irFactory.buildFun { updateFrom(jvmStaticFunction) name = jvmStaticFunction.name returnType = jvmStaticFunction.returnType }.apply { parent = companion.parent - copyTypeParametersFrom(jvmStaticFunction) + copyAttributes(jvmStaticFunction) copyAnnotationsFrom(jvmStaticFunction) - extensionReceiverParameter = jvmStaticFunction.extensionReceiverParameter?.copyTo(this) - valueParameters = jvmStaticFunction.valueParameters.map { it.copyTo(this) } + copyCorrespondingPropertyFrom(jvmStaticFunction) + copyParameterDeclarationsFrom(jvmStaticFunction) + dispatchReceiverParameter = null + metadata = jvmStaticFunction.metadata } staticExternal to companion.makeProxy(staticExternal, isStatic = false) } else { diff --git a/compiler/testData/codegen/box/external/jvmStaticExternal.kt b/compiler/testData/codegen/box/external/jvmStaticExternal.kt index c46b5ce7382..5f842eb8979 100644 --- a/compiler/testData/codegen/box/external/jvmStaticExternal.kt +++ b/compiler/testData/codegen/box/external/jvmStaticExternal.kt @@ -9,31 +9,44 @@ package foo class WithNative { companion object { @JvmStatic external fun bar(l: Long, s: String): Double + + @JvmStatic val prop: String external get } } object ObjWithNative { @JvmStatic external fun bar(l: Long, s: String): Double + + @JvmStatic val prop: String external get +} + +fun check(vararg allowed: String, block: () -> Unit) { + try { + block() + throw AssertionError("UnsatisfiedLinkError expected") + } catch (e: java.lang.UnsatisfiedLinkError) { + if (allowed.none { it == e.message }) { + throw AssertionError("fail: ${e.message}") + } + } } fun box(): String { - var d = 0.0 - try { - d = WithNative.bar(1, "") - return "Link error expected" - } - catch (e: java.lang.UnsatisfiedLinkError) { - if (e.message != "foo.WithNative.bar(JLjava/lang/String;)D" && - e.message != "'double foo.WithNative.bar(long, java.lang.String)'") return "Fail 1: " + e.message - } - - try { - d = ObjWithNative.bar(1, "") - return "Link error expected on object" - } - catch (e: java.lang.UnsatisfiedLinkError) { - if (e.message != "foo.ObjWithNative.bar(JLjava/lang/String;)D" && - e.message != "'double foo.ObjWithNative.bar(long, java.lang.String)'") return "Fail 2: " + e.message - } + check( + "foo.WithNative.bar(JLjava/lang/String;)D", + "'double foo.WithNative.bar(long, java.lang.String)'" + ) { WithNative.bar(1, "") } + check( + "foo.ObjWithNative.bar(JLjava/lang/String;)D", + "'double foo.ObjWithNative.bar(long, java.lang.String)'" + ) { ObjWithNative.bar(1, "") } + check( + "foo.WithNative.getProp()Ljava/lang/String;", + "'java.lang.String foo.WithNative.getProp()'" + ) { WithNative.prop } + check( + "foo.ObjWithNative.getProp()Ljava/lang/String;", + "'java.lang.String foo.ObjWithNative.getProp()'" + ) { ObjWithNative.prop } return "OK" }