JVM_IR: flexible nullability as annotation
We carry information about flexible nullability of IrType as an annotation, so there is no need to look at its underlying KotlinType.
This commit is contained in:
+30
@@ -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"))
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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"));
|
||||
|
||||
Reference in New Issue
Block a user