Prohibit @JvnName on functions mangled because of return type
This commit is contained in:
@@ -10,7 +10,8 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
@@ -23,7 +24,7 @@ fun getManglingSuffixBasedOnKotlinSignature(descriptor: CallableMemberDescriptor
|
|||||||
|
|
||||||
// If a function accepts inline class parameters, mangle its name.
|
// If a function accepts inline class parameters, mangle its name.
|
||||||
val actualValueParameterTypes = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
|
val actualValueParameterTypes = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
|
||||||
if (requiresFunctionNameMangling(actualValueParameterTypes)) {
|
if (requiresFunctionNameManglingForParameterTypes(actualValueParameterTypes)) {
|
||||||
return "-" + md5base64(collectSignatureForMangling(actualValueParameterTypes))
|
return "-" + md5base64(collectSignatureForMangling(actualValueParameterTypes))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,8 +33,7 @@ fun getManglingSuffixBasedOnKotlinSignature(descriptor: CallableMemberDescriptor
|
|||||||
// should unwrap it and take original return type instead.
|
// should unwrap it and take original return type instead.
|
||||||
if (descriptor.containingDeclaration is ClassDescriptor) {
|
if (descriptor.containingDeclaration is ClassDescriptor) {
|
||||||
val returnType = descriptor.unwrapInitialDescriptorForSuspendFunction().returnType!!
|
val returnType = descriptor.unwrapInitialDescriptorForSuspendFunction().returnType!!
|
||||||
// NB functions returning all inline classes (including our special 'kotlin.Result') should be mangled.
|
if (requiresFunctionNameManglingForReturnType(returnType)) {
|
||||||
if (returnType.isInlineClassType()) {
|
|
||||||
return "-" + md5base64(":" + getSignatureElementForMangling(returnType))
|
return "-" + md5base64(":" + getSignatureElementForMangling(returnType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -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.annotations.hasJvmFieldAnnotation
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||||
import org.jetbrains.kotlin.resolve.jvm.isInlineClassThatRequiresMangling
|
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 {
|
class LocalFunInlineChecker : DeclarationChecker {
|
||||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||||
@@ -148,7 +150,8 @@ class JvmNameAnnotationChecker : DeclarationChecker {
|
|||||||
if (DescriptorUtils.isOverride(descriptor) || descriptor.isOverridable) {
|
if (DescriptorUtils.isOverride(descriptor) || descriptor.isOverridable) {
|
||||||
diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_JVM_NAME.on(annotationEntry))
|
diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_JVM_NAME.on(annotationEntry))
|
||||||
} else if (descriptor.containingDeclaration.isInlineClassThatRequiresMangling() ||
|
} 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))
|
diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_JVM_NAME.on(annotationEntry))
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -11,3 +11,17 @@ fun bar(f: Foo) {}
|
|||||||
|
|
||||||
@JvmName("good")
|
@JvmName("good")
|
||||||
fun baz(r: Result<Int>) {}
|
fun baz(r: Result<Int>) {}
|
||||||
|
|
||||||
|
@JvmName("test")
|
||||||
|
fun returnsInlineClass() = Foo(1)
|
||||||
|
|
||||||
|
@JvmName("test")
|
||||||
|
fun returnsKotlinResult(a: Result<Int>): Result<Int> = a
|
||||||
|
|
||||||
|
class C {
|
||||||
|
@JvmName("test")
|
||||||
|
fun returnsInlineClass() = Foo(1)
|
||||||
|
|
||||||
|
@JvmName("test")
|
||||||
|
fun returnsKotlinResult(a: Result<Int>): Result<Int> = a
|
||||||
|
}
|
||||||
+14
@@ -11,3 +11,17 @@ fun bar(f: Foo) {}
|
|||||||
|
|
||||||
@JvmName("good")
|
@JvmName("good")
|
||||||
fun baz(r: Result<Int>) {}
|
fun baz(r: Result<Int>) {}
|
||||||
|
|
||||||
|
@JvmName("test")
|
||||||
|
fun returnsInlineClass() = Foo(1)
|
||||||
|
|
||||||
|
@JvmName("test")
|
||||||
|
fun returnsKotlinResult(a: Result<Int>): Result<Int> = a
|
||||||
|
|
||||||
|
class C {
|
||||||
|
<!INAPPLICABLE_JVM_NAME!>@JvmName("test")<!>
|
||||||
|
fun returnsInlineClass() = Foo(1)
|
||||||
|
|
||||||
|
<!INAPPLICABLE_JVM_NAME!>@JvmName("test")<!>
|
||||||
|
fun returnsKotlinResult(a: Result<Int>): Result<Int> = a
|
||||||
|
}
|
||||||
+11
@@ -2,6 +2,17 @@ package
|
|||||||
|
|
||||||
@kotlin.jvm.JvmName(name = "bad") public fun bar(/*0*/ f: Foo): kotlin.Unit
|
@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.Int>): kotlin.Unit
|
@kotlin.jvm.JvmName(name = "good") public fun baz(/*0*/ r: kotlin.Result<kotlin.Int>): kotlin.Unit
|
||||||
|
@kotlin.jvm.JvmName(name = "test") public fun returnsInlineClass(): Foo
|
||||||
|
@kotlin.jvm.JvmName(name = "test") public fun returnsKotlinResult(/*0*/ a: kotlin.Result<kotlin.Int>): kotlin.Result<kotlin.Int>
|
||||||
|
|
||||||
|
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.Int>): kotlin.Result<kotlin.Int>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
public final inline class Foo {
|
public final inline class Foo {
|
||||||
public constructor Foo(/*0*/ x: kotlin.Int)
|
public constructor Foo(/*0*/ x: kotlin.Int)
|
||||||
|
|||||||
+2
-1
@@ -272,7 +272,8 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
private fun checkOriginalAndFirTestdataIdentity(testDataFile: File, firTestDataFile: File) {
|
private fun checkOriginalAndFirTestdataIdentity(testDataFile: File, firTestDataFile: File) {
|
||||||
val originalTestData = loadTestDataWithoutDiagnostics(testDataFile)
|
val originalTestData = loadTestDataWithoutDiagnostics(testDataFile)
|
||||||
val firTestData = loadTestDataWithoutDiagnostics(firTestDataFile)
|
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)
|
TestCase.assertEquals(message, originalTestData, firTestData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-5
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||||
|
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
|
|
||||||
@@ -20,20 +21,24 @@ fun shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor: Callabl
|
|||||||
|
|
||||||
// TODO inner class in inline class
|
// TODO inner class in inline class
|
||||||
|
|
||||||
return constructorDescriptor.valueParameters.any { it.type.requiresFunctionNameMangling() }
|
return constructorDescriptor.valueParameters.any { it.type.requiresFunctionNameManglingInParameterTypes() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requiresFunctionNameMangling(valueParameterTypes: List<KotlinType>): Boolean {
|
fun requiresFunctionNameManglingForParameterTypes(valueParameterTypes: List<KotlinType>): Boolean {
|
||||||
return valueParameterTypes.any { it.requiresFunctionNameMangling() }
|
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 =
|
fun DeclarationDescriptor.isInlineClassThatRequiresMangling(): Boolean =
|
||||||
isInlineClass() && !isDontMangleClass(this as ClassDescriptor)
|
isInlineClass() && !isDontMangleClass(this as ClassDescriptor)
|
||||||
|
|
||||||
fun KotlinType.isInlineClassThatRequiresMangling() =
|
fun KotlinType.isInlineClassThatRequiresMangling() =
|
||||||
constructor.declarationDescriptor?.isInlineClassThatRequiresMangling() == true
|
constructor.declarationDescriptor?.isInlineClassThatRequiresMangling() == true
|
||||||
|
|
||||||
private fun KotlinType.requiresFunctionNameMangling() =
|
private fun KotlinType.requiresFunctionNameManglingInParameterTypes() =
|
||||||
isInlineClassThatRequiresMangling() || isTypeParameterWithUpperBoundThatRequiresMangling()
|
isInlineClassThatRequiresMangling() || isTypeParameterWithUpperBoundThatRequiresMangling()
|
||||||
|
|
||||||
private fun isDontMangleClass(classDescriptor: ClassDescriptor) =
|
private fun isDontMangleClass(classDescriptor: ClassDescriptor) =
|
||||||
@@ -41,5 +46,5 @@ private fun isDontMangleClass(classDescriptor: ClassDescriptor) =
|
|||||||
|
|
||||||
private fun KotlinType.isTypeParameterWithUpperBoundThatRequiresMangling(): Boolean {
|
private fun KotlinType.isTypeParameterWithUpperBoundThatRequiresMangling(): Boolean {
|
||||||
val descriptor = constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
|
val descriptor = constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
|
||||||
return descriptor.representativeUpperBound.requiresFunctionNameMangling()
|
return descriptor.representativeUpperBound.requiresFunctionNameManglingInParameterTypes()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user