diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmGeneratorExtensions.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmGeneratorExtensions.kt index 141a099b3c0..a497efd142f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmGeneratorExtensions.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmGeneratorExtensions.kt @@ -5,14 +5,22 @@ 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.KotlinBuiltIns import org.jetbrains.kotlin.codegen.SamType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations +import org.jetbrains.kotlin.ir.builders.declarations.addConstructor import org.jetbrains.kotlin.ir.builders.declarations.buildClass import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor 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.symbols.impl.DescriptorlessExternalPackageFragmentSymbol +import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor @@ -20,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.Name import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation @@ -95,4 +104,25 @@ class JvmGeneratorExtensions(private val generateFacades: Boolean = true) : Gene override fun getParentClassStaticScope(descriptor: ClassDescriptor): MemberScope? = descriptor.getParentJavaStaticClassScope() + + private val annotationPackage = + IrExternalPackageFragmentImpl(DescriptorlessExternalPackageFragmentSymbol(), KotlinBuiltIns.ANNOTATION_PACKAGE_FQ_NAME) + + private val flexibleNullabilityAnnotationClass = IrFactoryImpl.buildClass { + kind = ClassKind.ANNOTATION_CLASS + name = FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME.shortName() + }.apply { + createImplicitParameterDeclarationWithWrappedDescriptor() + parent = annotationPackage + addConstructor { + isPrimary = true + } + } + + override val flexibleNullabilityAnnotationConstructor: IrConstructor? = flexibleNullabilityAnnotationClass.constructors.single() + + companion object { + val FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME = + KotlinBuiltIns.ANNOTATION_PACKAGE_FQ_NAME.child(Name.identifier("FlexibleNullability")) + } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt index c61c27d12a9..a11366b0a32 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.AsmUtil @@ -39,7 +40,6 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext -import org.jetbrains.kotlin.types.isNullabilityFlexible import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.org.objectweb.asm.AnnotationVisitor import org.jetbrains.org.objectweb.asm.Type @@ -158,7 +158,7 @@ abstract class AnnotationCodegen( } // A flexible type whose lower bound in not-null and upper bound is nullable, should not be annotated - if (type.toKotlinType().isNullabilityFlexible()) { + if (type.isNullabilityFlexible()) { return } @@ -185,6 +185,9 @@ abstract class AnnotationCodegen( val retentionPolicy = getRetentionPolicy(annotationClass) 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 + // 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. // (Otherwise we would've resolved the entry to the actual annotation class.) @@ -376,6 +379,9 @@ private fun IrClass.getAnnotationRetention(): KotlinRetention? { return KotlinRetention.valueOf(retentionArgumentValue.name.asString()) } +private fun IrType.isNullabilityFlexible(): Boolean = + hasAnnotation(JvmGeneratorExtensions.FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME) + // To be generalized to IrMemberAccessExpression as soon as properties get symbols. private fun IrConstructorCall.getValueArgument(name: Name): IrExpression? { val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/StubGeneratorExtensions.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/StubGeneratorExtensions.kt index ce7f33fca9f..1c074f8279d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/StubGeneratorExtensions.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/StubGeneratorExtensions.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -31,6 +32,9 @@ open class StubGeneratorExtensions { companion object Instance : EnhancedNullability() } + open val flexibleNullabilityAnnotationConstructor: IrConstructor? + get() = null + companion object { @JvmField val EMPTY = StubGeneratorExtensions() diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt index 77d053ba6c9..31b6425e95c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/TypeTranslator.kt @@ -14,8 +14,10 @@ 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 import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrTypeAbbreviation @@ -127,6 +129,15 @@ class TypeTranslator( else -> throw AssertionError("Unexpected type descriptor $ktTypeDescriptor :: ${ktTypeDescriptor::class}") } + if (flexibleApproximatedType.isNullabilityFlexible()) + extensions.flexibleNullabilityAnnotationConstructor?.let { flexibleTypeAnnotationConstructor -> + annotations += IrConstructorCallImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + flexibleTypeAnnotationConstructor.constructedClassType, + flexibleTypeAnnotationConstructor.symbol, + 0, 0, 0 + ) + } }.buildTypeProjection() } diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 6c23b406ffc..7c54adcf71d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -43,7 +43,7 @@ import static org.jetbrains.kotlin.utils.CollectionsKt.newHashSetWithExpectedSiz public abstract class KotlinBuiltIns { public static final Name BUILT_INS_PACKAGE_NAME = Name.identifier("kotlin"); public static final FqName BUILT_INS_PACKAGE_FQ_NAME = FqName.topLevel(BUILT_INS_PACKAGE_NAME); - private static final FqName ANNOTATION_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("annotation")); + public static final FqName ANNOTATION_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("annotation")); public static final FqName COLLECTIONS_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("collections")); public static final FqName RANGES_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("ranges")); public static final FqName TEXT_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("text"));