Prohibit @JvmName on functions that are assumed to be mangled

#KT-26454 In Progress
This commit is contained in:
Mikhail Zarechenskiy
2018-09-10 10:38:23 +03:00
parent 5f50977974
commit 55ef96e5c9
8 changed files with 52 additions and 9 deletions
@@ -34,11 +34,14 @@ import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithCorres
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.annotations.VOLATILE_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
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
class LocalFunInlineChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
@@ -143,6 +146,10 @@ class JvmNameAnnotationChecker : DeclarationChecker {
if (descriptor is CallableMemberDescriptor) {
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 })
) {
diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_JVM_NAME.on(annotationEntry))
}
}
}
@@ -0,0 +1,13 @@
// !LANGUAGE: +InlineClasses
// !DIAGNOSTICS: -UNUSED_PARAMETER
inline class Foo(val x: Int) {
<!INAPPLICABLE_JVM_NAME!>@JvmName("other")<!>
fun simple() {}
}
<!INAPPLICABLE_JVM_NAME!>@JvmName("bad")<!>
fun bar(f: Foo) {}
@JvmName("good")
fun baz(r: Result<Int>) {}
@@ -0,0 +1,13 @@
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.Int>): kotlin.Unit
public final inline class Foo {
public constructor Foo(/*0*/ x: kotlin.Int)
public final val x: kotlin.Int
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
@kotlin.jvm.JvmName(name = "other") public final fun simple(): kotlin.Unit
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
@@ -3,22 +3,18 @@
fun foo(x: Int): Int = 0
@JvmName("fooUInt")
fun foo(x: UInt): String = ""
fun foo(x: UByte): String = ""
fun foo(x: UShort): String = ""
fun foo(x: ULong): String = ""
fun fooByte(x: Byte): Int = 0
@JvmName("fooUByte")
fun fooByte(x: UByte): String = ""
fun fooShort(x: Short): Int = 0
@JvmName("fooUByte")
fun fooShort(x: UShort): String = ""
fun fooLong(x: Long): Int = 0
@JvmName("fooULong")
fun fooLong(x: ULong): String = ""
fun test() {
@@ -2,13 +2,13 @@ package
public fun foo(/*0*/ x: kotlin.Int): kotlin.Int
public fun foo(/*0*/ x: kotlin.UByte): kotlin.String
@kotlin.jvm.JvmName(name = "fooUInt") public fun foo(/*0*/ x: kotlin.UInt): kotlin.String
public fun foo(/*0*/ x: kotlin.UInt): kotlin.String
public fun foo(/*0*/ x: kotlin.ULong): kotlin.String
public fun foo(/*0*/ x: kotlin.UShort): kotlin.String
public fun fooByte(/*0*/ x: kotlin.Byte): kotlin.Int
@kotlin.jvm.JvmName(name = "fooUByte") public fun fooByte(/*0*/ x: kotlin.UByte): kotlin.String
public fun fooByte(/*0*/ x: kotlin.UByte): kotlin.String
public fun fooLong(/*0*/ x: kotlin.Long): kotlin.Int
@kotlin.jvm.JvmName(name = "fooULong") public fun fooLong(/*0*/ x: kotlin.ULong): kotlin.String
public fun fooLong(/*0*/ x: kotlin.ULong): kotlin.String
public fun fooShort(/*0*/ x: kotlin.Short): kotlin.Int
@kotlin.jvm.JvmName(name = "fooUByte") public fun fooShort(/*0*/ x: kotlin.UShort): kotlin.String
public fun fooShort(/*0*/ x: kotlin.UShort): kotlin.String
public fun test(): kotlin.Unit
@@ -243,6 +243,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmName.kt");
}
@TestMetadata("jvmNameOnMangledNames.kt")
public void testJvmNameOnMangledNames() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.kt");
}
@TestMetadata("multifileClassPart.kt")
public void testMultifileClassPart() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPart.kt");
@@ -243,6 +243,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmName.kt");
}
@TestMetadata("jvmNameOnMangledNames.kt")
public void testJvmNameOnMangledNames() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/jvmNameOnMangledNames.kt");
}
@TestMetadata("multifileClassPart.kt")
public void testMultifileClassPart() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPart.kt");
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.load.kotlin.getRepresentativeUpperBound
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.types.KotlinType
import java.security.MessageDigest
@@ -29,11 +30,14 @@ fun requiresFunctionNameMangling(valueParameterTypes: List<KotlinType>): Boolean
return valueParameterTypes.any { it.requiresFunctionNameMangling() }
}
fun DeclarationDescriptor.isInlineClassThatRequiresMangling(): Boolean =
isInlineClass() && !isDontMangleClass(this as ClassDescriptor)
private fun KotlinType.requiresFunctionNameMangling() =
isInlineClassThatRequiresMangling() || isTypeParameterWithUpperBoundThatRequiresMangling()
private fun KotlinType.isInlineClassThatRequiresMangling() =
isInlineClassType() && !isDontMangleClass(this.constructor.declarationDescriptor as ClassDescriptor)
constructor.declarationDescriptor?.isInlineClassThatRequiresMangling() == true
private fun isDontMangleClass(classDescriptor: ClassDescriptor) =
classDescriptor.fqNameSafe == DescriptorUtils.RESULT_FQ_NAME