Inline classes. Use inline class instead of underlying type

in annotations if underlying type is not nullable reference type.
Previously, it worked only for inline classes with primitive
underlying type and nullable reference type.

 #KT-44133
This commit is contained in:
Ilmir Usmanov
2021-09-20 23:25:18 +02:00
committed by Space
parent 80fbc262b3
commit e74e267d16
3 changed files with 45 additions and 15 deletions
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.JvmSymbols import org.jetbrains.kotlin.backend.jvm.JvmSymbols
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
import org.jetbrains.kotlin.backend.jvm.ir.isWithFlexibleNullability import org.jetbrains.kotlin.backend.jvm.ir.isWithFlexibleNullability
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
@@ -38,6 +39,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -275,12 +277,12 @@ abstract class AnnotationCodegen(
visitor.visitEnd() visitor.visitEnd()
} }
is IrClassReference -> { is IrClassReference -> {
var classType = value.classType val classType = value.classType
classType.classOrNull?.owner?.let(innerClassConsumer::addInnerClassInfoFromAnnotation) classType.classOrNull?.owner?.let(innerClassConsumer::addInnerClassInfoFromAnnotation)
if (classType.isInlineClassType()) { val mappedType =
classType = classType.makeNullable() if (classType.isInlineClassType()) typeMapper.mapClass(classType.erasedUpperBound)
} else typeMapper.mapType(classType)
annotationVisitor.visit(name, typeMapper.mapType(classType)) annotationVisitor.visit(name, mappedType)
} }
is IrErrorExpression -> error("Don't know how to compile annotation value ${ir2string(value)}") is IrErrorExpression -> error("Don't know how to compile annotation value ${ir2string(value)}")
else -> error("Unsupported compile-time value ${ir2string(value)}") else -> error("Unsupported compile-time value ${ir2string(value)}")
@@ -1,17 +1,45 @@
// WITH_REFLECT // WITH_REFLECT
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
package test package test
import kotlin.reflect.KClass import kotlin.reflect.KClass
inline class IC(val i: Int) @JvmInline
value class ICInt(val i: Int)
@JvmInline
value class ICIntN(val i: Int?)
@JvmInline
value class ICAny(val a: Any)
annotation class Ann(val c: KClass<*>) annotation class Ann(val c: KClass<*>)
@Ann(IC::class) @Ann(ICInt::class)
class C class CInt
@Ann(ICIntN::class)
class CIntN
@Ann(ICAny::class)
class CAny
@Ann(Result::class)
class CResult
fun box(): String { fun box(): String {
val klass = (C::class.annotations.first() as Ann).c.toString() var klass = (CInt::class.annotations.first() as Ann).c.toString()
return if (klass == "class test.IC") "OK" else klass if (klass != "class test.ICInt") return "Expected class test.ICInt, got $klass"
klass = (CIntN::class.annotations.first() as Ann).c.toString()
if (klass != "class test.ICIntN") return "Expected class test.ICIntN, got $klass"
klass = (CAny::class.annotations.first() as Ann).c.toString()
if (klass != "class test.ICAny") return "Expected class test.ICAny, got $klass"
klass = (CResult::class.annotations.first() as Ann).c.toString()
if (klass != "class kotlin.Result") return "Expected class kotlin.Result, got $klass"
return "OK"
} }
@@ -15174,6 +15174,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/inlineClassWithCustomEquals.kt"); runTest("compiler/testData/codegen/box/inlineClasses/inlineClassWithCustomEquals.kt");
} }
@TestMetadata("kclassInAnnotation.kt")
public void ignoreKclassInAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kclassInAnnotation.kt");
}
@TestMetadata("kt31994.kt") @TestMetadata("kt31994.kt")
public void ignoreKt31994() throws Exception { public void ignoreKt31994() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt31994.kt"); runTest("compiler/testData/codegen/box/inlineClasses/kt31994.kt");
@@ -15702,11 +15707,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/jvmStaticVarInInlineClassCompanion.kt"); runTest("compiler/testData/codegen/box/inlineClasses/jvmStaticVarInInlineClassCompanion.kt");
} }
@TestMetadata("kclassInAnnotation.kt")
public void testKclassInAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kclassInAnnotation.kt");
}
@TestMetadata("kt25246.kt") @TestMetadata("kt25246.kt")
public void testKt25246() throws Exception { public void testKt25246() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt25246.kt"); runTest("compiler/testData/codegen/box/inlineClasses/kt25246.kt");