Do not generate TYPE_USE/TYPE_PARAMETER when compiling against JDK 1.6

#KT-53712
This commit is contained in:
Alexander Udalov
2022-08-26 00:39:05 +02:00
parent 0d2e9e7013
commit a09fd45ade
9 changed files with 79 additions and 11 deletions
@@ -281,6 +281,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt"); runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt");
} }
@Test
@TestMetadata("noTypeUseIfDependOnJvm6.kt")
public void testNoTypeUseIfDependOnJvm6() throws Exception {
runTest("compiler/testData/codegen/box/annotations/noTypeUseIfDependOnJvm6.kt");
}
@Test @Test
@TestMetadata("objectConstValInAnnotationArgument.kt") @TestMetadata("objectConstValInAnnotationArgument.kt")
public void testObjectConstValInAnnotationArgument() throws Exception { public void testObjectConstValInAnnotationArgument() throws Exception {
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.org.objectweb.asm.Type
import java.lang.annotation.ElementType import java.lang.annotation.ElementType
internal val additionalClassAnnotationPhase = makeIrFilePhase( internal val additionalClassAnnotationPhase = makeIrFilePhase(
@@ -37,6 +39,10 @@ internal val additionalClassAnnotationPhase = makeIrFilePhase(
private class AdditionalClassAnnotationLowering(private val context: JvmBackendContext) : ClassLoweringPass { private class AdditionalClassAnnotationLowering(private val context: JvmBackendContext) : ClassLoweringPass {
private val symbols = context.ir.symbols.javaAnnotations private val symbols = context.ir.symbols.javaAnnotations
private val isCompilingAgainstJdk8OrLater =
context.state.jvmBackendClassResolver.resolveToClassDescriptors(
Type.getObjectType("java/lang/invoke/LambdaMetafactory")
).isNotEmpty()
override fun lower(irClass: IrClass) { override fun lower(irClass: IrClass) {
if (!irClass.isAnnotationClass) return if (!irClass.isAnnotationClass) return
@@ -78,10 +84,9 @@ private class AdditionalClassAnnotationLowering(private val context: JvmBackendC
private fun generateTargetAnnotation(irClass: IrClass) { private fun generateTargetAnnotation(irClass: IrClass) {
if (irClass.hasAnnotation(JvmAnnotationNames.TARGET_ANNOTATION)) return if (irClass.hasAnnotation(JvmAnnotationNames.TARGET_ANNOTATION)) return
val annotationTargetMap = symbols.getAnnotationTargetMap(context.state.target)
val targets = irClass.applicableTargetSet() ?: return val targets = irClass.applicableTargetSet() ?: return
val javaTargets = targets.mapNotNullTo(HashSet()) { annotationTargetMap[it] }.sortedBy { val javaTargets = targets.mapNotNullTo(HashSet(), ::mapTarget).sortedBy {
ElementType.valueOf(it.symbol.owner.name.asString()) ElementType.valueOf(it.symbol.owner.name.asString())
} }
@@ -106,6 +111,13 @@ private class AdditionalClassAnnotationLowering(private val context: JvmBackendC
} }
} }
private fun mapTarget(target: KotlinTarget): IrEnumEntry? =
when (target) {
KotlinTarget.TYPE_PARAMETER -> symbols.typeParameterTarget.takeUnless { isCompilingAgainstJdk8OrLater }
KotlinTarget.TYPE -> symbols.typeUseTarget.takeUnless { isCompilingAgainstJdk8OrLater }
else -> symbols.jvmTargetMap[target]
}
private fun generateRepeatableAnnotation(irClass: IrClass) { private fun generateRepeatableAnnotation(irClass: IrClass) {
if (!irClass.hasAnnotation(StandardNames.FqNames.repeatable) || if (!irClass.hasAnnotation(StandardNames.FqNames.repeatable) ||
irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION) irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION)
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_CALL_RESULT_NAME import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_CALL_RESULT_NAME
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_CREATE_METHOD_NAME import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_CREATE_METHOD_NAME
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.InlineClassRepresentation import org.jetbrains.kotlin.descriptors.InlineClassRepresentation
@@ -1120,7 +1119,7 @@ class JvmSymbols(
KotlinRetention.RUNTIME to rpRuntime KotlinRetention.RUNTIME to rpRuntime
) )
private val jvm6TargetMap = mutableMapOf( val jvmTargetMap = mutableMapOf(
KotlinTarget.CLASS to buildEnumEntry(elementTypeEnum, "TYPE"), KotlinTarget.CLASS to buildEnumEntry(elementTypeEnum, "TYPE"),
KotlinTarget.ANNOTATION_CLASS to buildEnumEntry(elementTypeEnum, "ANNOTATION_TYPE"), KotlinTarget.ANNOTATION_CLASS to buildEnumEntry(elementTypeEnum, "ANNOTATION_TYPE"),
KotlinTarget.CONSTRUCTOR to buildEnumEntry(elementTypeEnum, "CONSTRUCTOR"), KotlinTarget.CONSTRUCTOR to buildEnumEntry(elementTypeEnum, "CONSTRUCTOR"),
@@ -1132,13 +1131,8 @@ class JvmSymbols(
KotlinTarget.VALUE_PARAMETER to buildEnumEntry(elementTypeEnum, "PARAMETER") KotlinTarget.VALUE_PARAMETER to buildEnumEntry(elementTypeEnum, "PARAMETER")
) )
private val jvm8TargetMap = jvm6TargetMap + mutableMapOf( val typeParameterTarget = buildEnumEntry(elementTypeEnum, "TYPE_PARAMETER")
KotlinTarget.TYPE_PARAMETER to buildEnumEntry(elementTypeEnum, "TYPE_PARAMETER"), val typeUseTarget = buildEnumEntry(elementTypeEnum, "TYPE_USE")
KotlinTarget.TYPE to buildEnumEntry(elementTypeEnum, "TYPE_USE")
)
fun getAnnotationTargetMap(target: JvmTarget): Map<KotlinTarget, IrEnumEntry> =
if (target == JvmTarget.JVM_1_6) jvm6TargetMap else jvm8TargetMap
} }
companion object { companion object {
@@ -0,0 +1,36 @@
// This test checks that we don't generate target TYPE_USE if there's JDK 1.6 in the classpath.
// It's important that this test depends on _mock JDK_, which doesn't have ElementType.TYPE_USE.
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// WITH_STDLIB
import kotlin.annotation.AnnotationTarget.*
@Target(
CLASS,
ANNOTATION_CLASS,
TYPE_PARAMETER,
PROPERTY,
FIELD,
LOCAL_VARIABLE,
VALUE_PARAMETER,
CONSTRUCTOR,
FUNCTION,
PROPERTY_GETTER,
PROPERTY_SETTER,
TYPE,
EXPRESSION,
FILE,
TYPEALIAS,
)
@Retention(AnnotationRetention.SOURCE)
annotation class A
fun box(): String {
val targets = A::class.java.getAnnotation(java.lang.annotation.Target::class.java).value
if (targets.toList().toString() != "[TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE]")
return "Fail: Java annotation target list should not contain TYPE_USE/TYPE_PARAMETER: ${targets.toList()}"
return "OK"
}
@@ -1,4 +1,5 @@
// !LANGUAGE: +UseGetterNameForPropertyAnnotationsMethodOnJvm // !LANGUAGE: +UseGetterNameForPropertyAnnotationsMethodOnJvm
// FULL_JDK
@Target(AnnotationTarget.PROPERTY) @Target(AnnotationTarget.PROPERTY)
annotation class AnnProperty annotation class AnnProperty
@@ -1,3 +1,5 @@
// FULL_JDK
annotation class Anno annotation class Anno
@Target(AnnotationTarget.TYPE) @Target(AnnotationTarget.TYPE)
@@ -269,6 +269,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt"); runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt");
} }
@Test
@TestMetadata("noTypeUseIfDependOnJvm6.kt")
public void testNoTypeUseIfDependOnJvm6() throws Exception {
runTest("compiler/testData/codegen/box/annotations/noTypeUseIfDependOnJvm6.kt");
}
@Test @Test
@TestMetadata("parameterAnnotationInDefaultImpls.kt") @TestMetadata("parameterAnnotationInDefaultImpls.kt")
public void testParameterAnnotationInDefaultImpls() throws Exception { public void testParameterAnnotationInDefaultImpls() throws Exception {
@@ -281,6 +281,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt"); runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt");
} }
@Test
@TestMetadata("noTypeUseIfDependOnJvm6.kt")
public void testNoTypeUseIfDependOnJvm6() throws Exception {
runTest("compiler/testData/codegen/box/annotations/noTypeUseIfDependOnJvm6.kt");
}
@Test @Test
@TestMetadata("objectConstValInAnnotationArgument.kt") @TestMetadata("objectConstValInAnnotationArgument.kt")
public void testObjectConstValInAnnotationArgument() throws Exception { public void testObjectConstValInAnnotationArgument() throws Exception {
@@ -238,6 +238,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt"); runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt");
} }
@TestMetadata("noTypeUseIfDependOnJvm6.kt")
public void testNoTypeUseIfDependOnJvm6() throws Exception {
runTest("compiler/testData/codegen/box/annotations/noTypeUseIfDependOnJvm6.kt");
}
@TestMetadata("parameterAnnotationInDefaultImpls.kt") @TestMetadata("parameterAnnotationInDefaultImpls.kt")
public void testParameterAnnotationInDefaultImpls() throws Exception { public void testParameterAnnotationInDefaultImpls() throws Exception {
runTest("compiler/testData/codegen/box/annotations/parameterAnnotationInDefaultImpls.kt"); runTest("compiler/testData/codegen/box/annotations/parameterAnnotationInDefaultImpls.kt");