EnhancedNullability annotation in IR

Fixes KT-40115 & KT-40117.

Move FlexibleNullability annotation to 'kotlin.internal.ir'.
This commit is contained in:
Dmitry Petrov
2020-08-31 11:04:10 +03:00
parent 0bff406a12
commit 8cb8284957
29 changed files with 514 additions and 178 deletions
@@ -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
}
}
@@ -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 {