From 266a8dae3ffd936e7b6a231bf77601e476bf7c0f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 24 Oct 2018 14:36:54 +0200 Subject: [PATCH] Fix KClassValue behavior for reified type parameter literals #KT-27799 Open --- .../classLiteral/inAnnotationArguments.kt | 5 ++++- .../classLiteral/inAnnotationArguments.txt | 1 + .../annotations/classLiteralInAnnotation.txt | 7 +++---- .../kotlin/resolve/constants/constantValues.kt | 18 +++++++++++++++--- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt index c78bfd8c943..4757e47d376 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt @@ -32,4 +32,7 @@ fun test6() {} fun test7() {} @AnnArray(arrayOf(""::class, String::class, AnObject::class)) -fun test8() {} \ No newline at end of file +fun test8() {} + +inline val T.test9 + get() = @Ann(T::class) object {} diff --git a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.txt b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.txt index 44d2697e1c3..567e090119c 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.txt +++ b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.txt @@ -1,5 +1,6 @@ package +public val T.test9: kotlin.Any public fun foo(): kotlin.String @Ann(k = kotlin.String::class) public fun test1(): kotlin.Unit @Ann(k = kotlin.String::class) public fun test2(): kotlin.Unit diff --git a/compiler/testData/ir/irText/declarations/annotations/classLiteralInAnnotation.txt b/compiler/testData/ir/irText/declarations/annotations/classLiteralInAnnotation.txt index 57aee49eda2..4ab2d010ec9 100644 --- a/compiler/testData/ir/irText/declarations/annotations/classLiteralInAnnotation.txt +++ b/compiler/testData/ir/irText/declarations/annotations/classLiteralInAnnotation.txt @@ -59,7 +59,7 @@ FILE fqName: fileName:/classLiteralInAnnotation.kt CLASS CLASS name: modality:FINAL visibility:local flags: superTypes:[kotlin.Any] annotations: CALL 'constructor A(KClass<*>)' type=A origin=null - klass: CLASS_REFERENCE '' type=kotlin.reflect.KClass + klass: CLASS_REFERENCE 'Any' type=kotlin.reflect.KClass $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:test2. flags: CONSTRUCTOR visibility:public <> () returnType:test2. flags:primary BLOCK_BODY @@ -90,7 +90,7 @@ FILE fqName: fileName:/classLiteralInAnnotation.kt CLASS CLASS name: modality:FINAL visibility:local flags: superTypes:[kotlin.Any] annotations: CALL 'constructor A(KClass<*>)' type=A origin=null - klass: CLASS_REFERENCE '' type=kotlin.reflect.KClass + klass: CLASS_REFERENCE 'Any' type=kotlin.reflect.KClass $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:. flags: CONSTRUCTOR visibility:public <> () returnType:. flags:primary BLOCK_BODY @@ -122,7 +122,7 @@ FILE fqName: fileName:/classLiteralInAnnotation.kt CLASS CLASS name: modality:FINAL visibility:local flags: superTypes:[kotlin.Any] annotations: CALL 'constructor A(KClass<*>)' type=A origin=null - klass: CLASS_REFERENCE '' type=kotlin.reflect.KClass + klass: CLASS_REFERENCE 'Any' type=kotlin.reflect.KClass $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:. flags: CONSTRUCTOR visibility:public <> () returnType:. flags:primary BLOCK_BODY @@ -142,4 +142,3 @@ FILE fqName: fileName:/classLiteralInAnnotation.kt FUN IR_EXTERNAL_DECLARATION_STUB name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: $this: VALUE_PARAMETER name: type:kotlin.Any flags: CALL 'constructor ()' type=. origin=OBJECT_LITERAL - diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt index 2fd7728fb57..a080605583c 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/constantValues.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.constants import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -193,9 +194,20 @@ class KClassValue(value: ClassLiteralValue) : ConstantValue(v arrayDimensions++ } - val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null - val classId = descriptor.classId ?: return null - return KClassValue(classId, arrayDimensions) + return when (val descriptor = type.constructor.declarationDescriptor) { + is ClassDescriptor -> { + val classId = descriptor.classId ?: return null + KClassValue(classId, arrayDimensions) + } + is TypeParameterDescriptor -> { + // This is possible if a reified type parameter is used in annotation on a local class / anonymous object. + // In JVM class file, we can't represent such literal properly, so we're writing java.lang.Object instead. + // This has no effect on the compiler front-end or other back-ends, so we use kotlin.Any for simplicity here. + // Overall, it looks like such code should be disallowed: https://youtrack.jetbrains.com/issue/KT-27799 + KClassValue(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.any.toSafe()), 0) + } + else -> null + } } } }