Fix KClassValue behavior for reified type parameter literals

#KT-27799 Open
This commit is contained in:
Alexander Udalov
2018-10-24 14:36:54 +02:00
parent c1ab08c8ce
commit 266a8dae3f
4 changed files with 23 additions and 8 deletions
@@ -32,4 +32,7 @@ fun test6() {}
fun test7() {}
@AnnArray(arrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL!>""::class<!>, String::class, AnObject::class))
fun test8() {}
fun test8() {}
inline val <reified T> T.test9
get() = @Ann(T::class) object {}
@@ -1,5 +1,6 @@
package
public val </*0*/ reified T> 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
@@ -59,7 +59,7 @@ FILE fqName:<root> fileName:/classLiteralInAnnotation.kt
CLASS CLASS name:<no name provided> modality:FINAL visibility:local flags: superTypes:[kotlin.Any]
annotations:
CALL 'constructor A(KClass<*>)' type=A origin=null
klass: CLASS_REFERENCE '<reified T>' type=kotlin.reflect.KClass<T>
klass: CLASS_REFERENCE 'Any' type=kotlin.reflect.KClass<kotlin.Any>
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:test2.<no name provided><T> flags:
CONSTRUCTOR visibility:public <> () returnType:test2.<no name provided><T> flags:primary
BLOCK_BODY
@@ -90,7 +90,7 @@ FILE fqName:<root> fileName:/classLiteralInAnnotation.kt
CLASS CLASS name:<no name provided> modality:FINAL visibility:local flags: superTypes:[kotlin.Any]
annotations:
CALL 'constructor A(KClass<*>)' type=A origin=null
klass: CLASS_REFERENCE '<reified T>' type=kotlin.reflect.KClass<T>
klass: CLASS_REFERENCE 'Any' type=kotlin.reflect.KClass<kotlin.Any>
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<get-test3>.<no name provided> flags:
CONSTRUCTOR visibility:public <> () returnType:<get-test3>.<no name provided> flags:primary
BLOCK_BODY
@@ -122,7 +122,7 @@ FILE fqName:<root> fileName:/classLiteralInAnnotation.kt
CLASS CLASS name:<no name provided> modality:FINAL visibility:local flags: superTypes:[kotlin.Any]
annotations:
CALL 'constructor A(KClass<*>)' type=A origin=null
klass: CLASS_REFERENCE '<reified T>' type=kotlin.reflect.KClass<T>
klass: CLASS_REFERENCE 'Any' type=kotlin.reflect.KClass<kotlin.Any>
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<set-test3>.<no name provided> flags:
CONSTRUCTOR visibility:public <> () returnType:<set-test3>.<no name provided> flags:primary
BLOCK_BODY
@@ -142,4 +142,3 @@ FILE fqName:<root> 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:<this> type:kotlin.Any flags:
CALL 'constructor <no name provided>()' type=<set-test3>.<no name provided> origin=OBJECT_LITERAL
@@ -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<ClassLiteralValue>(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
}
}
}
}