EnhancedNullability annotation in IR
Fixes KT-40115 & KT-40117. Move FlexibleNullability annotation to 'kotlin.internal.ir'.
This commit is contained in:
+28
-6
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.codegen.SamType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
|
||||
@@ -19,6 +18,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.load.java.descriptors.getParentJavaStaticClassScope
|
||||
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
@@ -105,24 +106,45 @@ class JvmGeneratorExtensions(private val generateFacades: Boolean = true) : Gene
|
||||
override fun getParentClassStaticScope(descriptor: ClassDescriptor): MemberScope? =
|
||||
descriptor.getParentJavaStaticClassScope()
|
||||
|
||||
private val annotationPackage =
|
||||
IrExternalPackageFragmentImpl(DescriptorlessExternalPackageFragmentSymbol(), StandardNames.ANNOTATION_PACKAGE_FQ_NAME)
|
||||
private val kotlinIrInternalPackage =
|
||||
IrExternalPackageFragmentImpl(DescriptorlessExternalPackageFragmentSymbol(), IrBuiltIns.KOTLIN_INTERNAL_IR_FQN)
|
||||
|
||||
private val kotlinJvmInternalPackage =
|
||||
IrExternalPackageFragmentImpl(DescriptorlessExternalPackageFragmentSymbol(), JvmAnnotationNames.KOTLIN_JVM_INTERNAL)
|
||||
|
||||
private val flexibleNullabilityAnnotationClass = IrFactoryImpl.buildClass {
|
||||
kind = ClassKind.ANNOTATION_CLASS
|
||||
name = FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME.shortName()
|
||||
}.apply {
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
parent = annotationPackage
|
||||
parent = kotlinIrInternalPackage
|
||||
addConstructor {
|
||||
isPrimary = true
|
||||
}
|
||||
}
|
||||
|
||||
override val flexibleNullabilityAnnotationConstructor: IrConstructor? = flexibleNullabilityAnnotationClass.constructors.single()
|
||||
private val enhancedNullabilityAnnotationClass = IrFactoryImpl.buildClass {
|
||||
kind = ClassKind.ANNOTATION_CLASS
|
||||
name = ENHANCED_NULLABILITY_ANNOTATION_FQ_NAME.shortName()
|
||||
}.apply {
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
parent = kotlinJvmInternalPackage
|
||||
addConstructor {
|
||||
isPrimary = true
|
||||
}
|
||||
}
|
||||
|
||||
override val flexibleNullabilityAnnotationConstructor: IrConstructor? =
|
||||
flexibleNullabilityAnnotationClass.constructors.single()
|
||||
|
||||
override val enhancedNullabilityAnnotationConstructor: IrConstructor? =
|
||||
enhancedNullabilityAnnotationClass.constructors.single()
|
||||
|
||||
companion object {
|
||||
val FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME =
|
||||
StandardNames.ANNOTATION_PACKAGE_FQ_NAME.child(Name.identifier("FlexibleNullability"))
|
||||
IrBuiltIns.KOTLIN_INTERNAL_IR_FQN.child(Name.identifier("FlexibleNullability"))
|
||||
|
||||
val ENHANCED_NULLABILITY_ANNOTATION_FQ_NAME: FqName =
|
||||
JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -186,7 +186,7 @@ abstract class AnnotationCodegen(
|
||||
if (retentionPolicy == RetentionPolicy.SOURCE) return null
|
||||
|
||||
// FlexibleNullability is an internal annotation, used only inside the compiler
|
||||
if (annotationClass.fqNameWhenAvailable == JvmGeneratorExtensions.FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME) return null
|
||||
if (annotationClass.fqNameWhenAvailable in internalAnnotations) return null
|
||||
|
||||
// We do not generate annotations whose classes are optional (annotated with `@OptionalExpectation`) because if an annotation entry
|
||||
// is resolved to the expected declaration, this means that annotation has no actual class, and thus should not be generated.
|
||||
@@ -296,9 +296,15 @@ abstract class AnnotationCodegen(
|
||||
KotlinRetention.RUNTIME to RetentionPolicy.RUNTIME
|
||||
)
|
||||
|
||||
internal val internalAnnotations = setOf(
|
||||
JvmGeneratorExtensions.FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME,
|
||||
JvmGeneratorExtensions.ENHANCED_NULLABILITY_ANNOTATION_FQ_NAME
|
||||
)
|
||||
|
||||
private fun getRetentionPolicy(irClass: IrClass): RetentionPolicy {
|
||||
val retention = irClass.getAnnotationRetention()
|
||||
if (retention != null) {
|
||||
@Suppress("MapGetWithNotNullAssertionOperator")
|
||||
return annotationRetentionMap[retention]!!
|
||||
}
|
||||
irClass.getAnnotation(FqName(java.lang.annotation.Retention::class.java.name))?.let { retentionAnnotation ->
|
||||
@@ -374,7 +380,7 @@ private val RETENTION_PARAMETER_NAME = Name.identifier("value")
|
||||
private fun IrClass.getAnnotationRetention(): KotlinRetention? {
|
||||
val retentionArgument =
|
||||
getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(RETENTION_PARAMETER_NAME)
|
||||
as? IrGetEnumValue?: return null
|
||||
as? IrGetEnumValue ?: return null
|
||||
val retentionArgumentValue = retentionArgument.symbol.owner
|
||||
return KotlinRetention.valueOf(retentionArgumentValue.name.asString())
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ open class StubGeneratorExtensions {
|
||||
open val flexibleNullabilityAnnotationConstructor: IrConstructor?
|
||||
get() = null
|
||||
|
||||
open val enhancedNullabilityAnnotationConstructor: IrConstructor?
|
||||
get() = null
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val EMPTY = StubGeneratorExtensions()
|
||||
|
||||
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
||||
@@ -87,9 +86,9 @@ class TypeTranslator(
|
||||
|
||||
when {
|
||||
flexibleApproximatedType.isError ->
|
||||
return IrErrorTypeImpl(flexibleApproximatedType, translateTypeAnnotations(flexibleApproximatedType.annotations), variance)
|
||||
return IrErrorTypeImpl(flexibleApproximatedType, translateTypeAnnotations(flexibleApproximatedType), variance)
|
||||
flexibleApproximatedType.isDynamic() ->
|
||||
return IrDynamicTypeImpl(flexibleApproximatedType, translateTypeAnnotations(flexibleApproximatedType.annotations), variance)
|
||||
return IrDynamicTypeImpl(flexibleApproximatedType, translateTypeAnnotations(flexibleApproximatedType), variance)
|
||||
}
|
||||
|
||||
val approximatedType = flexibleApproximatedType.upperIfFlexible()
|
||||
@@ -111,19 +110,19 @@ class TypeTranslator(
|
||||
|
||||
return IrSimpleTypeBuilder().apply {
|
||||
this.kotlinType = flexibleApproximatedType
|
||||
this.hasQuestionMark = approximatedType.isMarkedNullable || extensions.enhancedNullability.hasEnhancedNullability(approximatedType)
|
||||
this.hasQuestionMark = approximatedType.isMarkedNullable
|
||||
this.variance = variance
|
||||
this.abbreviation = approximatedType.getAbbreviation()?.toIrTypeAbbreviation()
|
||||
when (ktTypeDescriptor) {
|
||||
is TypeParameterDescriptor -> {
|
||||
classifier = resolveTypeParameter(ktTypeDescriptor)
|
||||
annotations = translateTypeAnnotations(approximatedType.annotations)
|
||||
annotations = translateTypeAnnotations(approximatedType)
|
||||
}
|
||||
|
||||
is ClassDescriptor -> {
|
||||
classifier = symbolTable.referenceClass(ktTypeDescriptor)
|
||||
arguments = translateTypeArguments(approximatedType.arguments)
|
||||
annotations = translateTypeAnnotations(approximatedType.annotations)
|
||||
annotations = translateTypeAnnotations(approximatedType)
|
||||
}
|
||||
|
||||
else ->
|
||||
@@ -155,7 +154,7 @@ class TypeTranslator(
|
||||
symbolTable.referenceTypeAlias(typeAliasDescriptor),
|
||||
isMarkedNullable,
|
||||
translateTypeArguments(this.arguments),
|
||||
translateTypeAnnotations(this.annotations)
|
||||
translateTypeAnnotations(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -195,8 +194,26 @@ class TypeTranslator(
|
||||
approximateCapturedTypes(ktType).upper
|
||||
}
|
||||
|
||||
private fun translateTypeAnnotations(annotations: Annotations): List<IrConstructorCall> =
|
||||
annotations.mapNotNull(constantValueGenerator::generateAnnotationConstructorCall)
|
||||
private fun translateTypeAnnotations(kotlinType: KotlinType): List<IrConstructorCall> {
|
||||
val annotations = kotlinType.annotations
|
||||
val irAnnotations = ArrayList<IrConstructorCall>()
|
||||
annotations.mapNotNullTo(irAnnotations) {
|
||||
constantValueGenerator.generateAnnotationConstructorCall(it)
|
||||
}
|
||||
// EnhancedNullability annotation is not present in 'annotations', see 'EnhancedTypeAnnotations::iterator()'.
|
||||
if (extensions.enhancedNullability.hasEnhancedNullability(kotlinType)) {
|
||||
extensions.enhancedNullabilityAnnotationConstructor?.let { irConstructor ->
|
||||
irAnnotations.add(
|
||||
IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
irConstructor.constructedClassType,
|
||||
irConstructor.symbol
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return irAnnotations
|
||||
}
|
||||
|
||||
private fun translateTypeArguments(arguments: List<TypeProjection>) =
|
||||
arguments.map {
|
||||
|
||||
Reference in New Issue
Block a user