diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/inlineClassManglingUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/inlineClassManglingUtils.kt index 5b7d20edbac..09e0b1d0f7d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/inlineClassManglingUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/inlineClassManglingUtils.kt @@ -10,7 +10,8 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.isInlineClassType -import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameMangling +import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes +import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound import java.security.MessageDigest @@ -23,7 +24,7 @@ fun getManglingSuffixBasedOnKotlinSignature(descriptor: CallableMemberDescriptor // If a function accepts inline class parameters, mangle its name. val actualValueParameterTypes = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type } - if (requiresFunctionNameMangling(actualValueParameterTypes)) { + if (requiresFunctionNameManglingForParameterTypes(actualValueParameterTypes)) { return "-" + md5base64(collectSignatureForMangling(actualValueParameterTypes)) } @@ -32,8 +33,7 @@ fun getManglingSuffixBasedOnKotlinSignature(descriptor: CallableMemberDescriptor // should unwrap it and take original return type instead. if (descriptor.containingDeclaration is ClassDescriptor) { val returnType = descriptor.unwrapInitialDescriptorForSuspendFunction().returnType!! - // NB functions returning all inline classes (including our special 'kotlin.Result') should be mangled. - if (returnType.isInlineClassType()) { + if (requiresFunctionNameManglingForReturnType(returnType)) { return "-" + md5base64(":" + getSignatureElementForMangling(returnType)) } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/declarationCheckers.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/declarationCheckers.kt index 3476e20380a..3854b6335ee 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/declarationCheckers.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/declarationCheckers.kt @@ -42,7 +42,9 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.findSynchronizedAnnotation import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.jvm.isInlineClassThatRequiresMangling -import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameMangling +import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes +import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType +import javax.rmi.CORBA.ClassDesc class LocalFunInlineChecker : DeclarationChecker { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { @@ -148,7 +150,8 @@ class JvmNameAnnotationChecker : DeclarationChecker { if (DescriptorUtils.isOverride(descriptor) || descriptor.isOverridable) { diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_JVM_NAME.on(annotationEntry)) } else if (descriptor.containingDeclaration.isInlineClassThatRequiresMangling() || - requiresFunctionNameMangling(descriptor.valueParameters.map { it.type }) + requiresFunctionNameManglingForParameterTypes(descriptor.valueParameters.map { it.type }) || + descriptor.containingDeclaration is ClassDescriptor && requiresFunctionNameManglingForReturnType(descriptor.returnType) ) { diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_JVM_NAME.on(annotationEntry)) } diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.fir.kt index 1a4c64ebb53..5e9065090ec 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.fir.kt @@ -10,4 +10,18 @@ inline class Foo(val x: Int) { fun bar(f: Foo) {} @JvmName("good") -fun baz(r: Result) {} \ No newline at end of file +fun baz(r: Result) {} + +@JvmName("test") +fun returnsInlineClass() = Foo(1) + +@JvmName("test") +fun returnsKotlinResult(a: Result): Result = a + +class C { + @JvmName("test") + fun returnsInlineClass() = Foo(1) + + @JvmName("test") + fun returnsKotlinResult(a: Result): Result = a +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.kt index 07807c3e31a..d97155c6640 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.kt @@ -10,4 +10,18 @@ inline class Foo(val x: Int) { fun bar(f: Foo) {} @JvmName("good") -fun baz(r: Result) {} \ No newline at end of file +fun baz(r: Result) {} + +@JvmName("test") +fun returnsInlineClass() = Foo(1) + +@JvmName("test") +fun returnsKotlinResult(a: Result): Result = a + +class C { + @JvmName("test") + fun returnsInlineClass() = Foo(1) + + @JvmName("test") + fun returnsKotlinResult(a: Result): Result = a +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.txt index c3e73ad3abe..3de842e413e 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.txt @@ -2,6 +2,17 @@ package @kotlin.jvm.JvmName(name = "bad") public fun bar(/*0*/ f: Foo): kotlin.Unit @kotlin.jvm.JvmName(name = "good") public fun baz(/*0*/ r: kotlin.Result): kotlin.Unit +@kotlin.jvm.JvmName(name = "test") public fun returnsInlineClass(): Foo +@kotlin.jvm.JvmName(name = "test") public fun returnsKotlinResult(/*0*/ a: kotlin.Result): kotlin.Result + +public final class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + @kotlin.jvm.JvmName(name = "test") public final fun returnsInlineClass(): Foo + @kotlin.jvm.JvmName(name = "test") public final fun returnsKotlinResult(/*0*/ a: kotlin.Result): kotlin.Result + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} public final inline class Foo { public constructor Foo(/*0*/ x: kotlin.Int) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt index 997e0a02573..738acd12f85 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt @@ -272,7 +272,8 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() { private fun checkOriginalAndFirTestdataIdentity(testDataFile: File, firTestDataFile: File) { val originalTestData = loadTestDataWithoutDiagnostics(testDataFile) val firTestData = loadTestDataWithoutDiagnostics(firTestDataFile) - val message = "Original and fir test data doesn't identical. Please, add changes from ${testDataFile.name} to ${firTestDataFile.name}" + val message = "Original and fir test data aren't identical. " + + "Please, add changes from ${testDataFile.name} to ${firTestDataFile.name}" TestCase.assertEquals(message, originalTestData, firTestData) } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/resolve/jvm/inlineClassManglingRules.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/resolve/jvm/inlineClassManglingRules.kt index 218d7b1ecaf..3179b231efb 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/resolve/jvm/inlineClassManglingRules.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/resolve/jvm/inlineClassManglingRules.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.isInlineClass +import org.jetbrains.kotlin.resolve.isInlineClassType import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound @@ -20,20 +21,24 @@ fun shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor: Callabl // TODO inner class in inline class - return constructorDescriptor.valueParameters.any { it.type.requiresFunctionNameMangling() } + return constructorDescriptor.valueParameters.any { it.type.requiresFunctionNameManglingInParameterTypes() } } -fun requiresFunctionNameMangling(valueParameterTypes: List): Boolean { - return valueParameterTypes.any { it.requiresFunctionNameMangling() } +fun requiresFunctionNameManglingForParameterTypes(valueParameterTypes: List): Boolean { + return valueParameterTypes.any { it.requiresFunctionNameManglingInParameterTypes() } } +// NB functions returning all inline classes (including our special 'kotlin.Result') should be mangled. +fun requiresFunctionNameManglingForReturnType(returnType: KotlinType?) = + returnType != null && returnType.isInlineClassType() + fun DeclarationDescriptor.isInlineClassThatRequiresMangling(): Boolean = isInlineClass() && !isDontMangleClass(this as ClassDescriptor) fun KotlinType.isInlineClassThatRequiresMangling() = constructor.declarationDescriptor?.isInlineClassThatRequiresMangling() == true -private fun KotlinType.requiresFunctionNameMangling() = +private fun KotlinType.requiresFunctionNameManglingInParameterTypes() = isInlineClassThatRequiresMangling() || isTypeParameterWithUpperBoundThatRequiresMangling() private fun isDontMangleClass(classDescriptor: ClassDescriptor) = @@ -41,5 +46,5 @@ private fun isDontMangleClass(classDescriptor: ClassDescriptor) = private fun KotlinType.isTypeParameterWithUpperBoundThatRequiresMangling(): Boolean { val descriptor = constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false - return descriptor.representativeUpperBound.requiresFunctionNameMangling() + return descriptor.representativeUpperBound.requiresFunctionNameManglingInParameterTypes() }