IR: move JVM-specific flexible types to backend.jvm

This commit is contained in:
Alexander Udalov
2021-06-30 23:03:49 +02:00
parent 2834c22a85
commit e2f462095d
4 changed files with 50 additions and 31 deletions
@@ -5,7 +5,35 @@
package org.jetbrains.kotlin.backend.jvm package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.jvm.ir.IrJvmFlexibleType
import org.jetbrains.kotlin.backend.jvm.ir.asJvmFlexibleType
import org.jetbrains.kotlin.backend.jvm.ir.isWithFlexibleNullability
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.types.model.FlexibleTypeMarker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
class JvmIrTypeSystemContext(override val irBuiltIns: IrBuiltIns) : IrTypeSystemContext class JvmIrTypeSystemContext(override val irBuiltIns: IrBuiltIns) : IrTypeSystemContext {
override fun KotlinTypeMarker.asFlexibleType(): FlexibleTypeMarker? =
(this as IrType).asJvmFlexibleType(irBuiltIns)
override fun FlexibleTypeMarker.upperBound(): SimpleTypeMarker {
return when (this) {
is IrJvmFlexibleType -> this.upperBound
else -> error("Unexpected flexible type ${this::class.java.simpleName}: $this")
}
}
override fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker {
return when (this) {
is IrJvmFlexibleType -> this.lowerBound
else -> error("Unexpected flexible type ${this::class.java.simpleName}: $this")
}
}
override fun KotlinTypeMarker.isMarkedNullable(): Boolean =
this is IrSimpleType && !isWithFlexibleNullability() && hasQuestionMark
}
@@ -23,6 +23,7 @@ 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.isInlineClassType import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
import org.jetbrains.kotlin.backend.jvm.ir.isWithFlexibleNullability
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.TypeAnnotationCollector import org.jetbrains.kotlin.codegen.TypeAnnotationCollector
@@ -43,7 +44,10 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.AnnotationVisitor
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.TypePath
import org.jetbrains.org.objectweb.asm.TypeReference
import java.lang.annotation.RetentionPolicy import java.lang.annotation.RetentionPolicy
abstract class AnnotationCodegen( abstract class AnnotationCodegen(
@@ -156,9 +160,7 @@ abstract class AnnotationCodegen(
} }
// A flexible type whose lower bound in not-null and upper bound is nullable, should not be annotated // A flexible type whose lower bound in not-null and upper bound is nullable, should not be annotated
if (type.isNullabilityFlexible()) { if (type.isWithFlexibleNullability()) return
return
}
val annotationClass = if (type.isNullable()) Nullable::class.java else NotNull::class.java val annotationClass = if (type.isNullable()) Nullable::class.java else NotNull::class.java
@@ -451,9 +453,6 @@ private fun IrClass.getAnnotationRetention(): KotlinRetention? {
return KotlinRetention.valueOf(retentionArgumentValue.name.asString()) return KotlinRetention.valueOf(retentionArgumentValue.name.asString())
} }
private fun IrType.isNullabilityFlexible(): Boolean =
hasAnnotation(JvmSymbols.FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME)
// To be generalized to IrMemberAccessExpression as soon as properties get symbols. // To be generalized to IrMemberAccessExpression as soon as properties get symbols.
private fun IrConstructorCall.getValueArgument(name: Name): IrExpression? { private fun IrConstructorCall.getValueArgument(name: Name): IrExpression? {
val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null
@@ -3,21 +3,25 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.ir.types package org.jetbrains.kotlin.backend.jvm.ir
import org.jetbrains.kotlin.backend.jvm.JvmSymbols
import org.jetbrains.kotlin.backend.jvm.codegen.isRawType
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.removeAnnotations
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.FlexibleTypeBoundsChecker import org.jetbrains.kotlin.types.FlexibleTypeBoundsChecker
import org.jetbrains.kotlin.types.model.FlexibleTypeMarker import org.jetbrains.kotlin.types.model.FlexibleTypeMarker
// TODO: extract properly to JVM-specific modules
internal interface IrJvmFlexibleType : FlexibleTypeMarker { internal interface IrJvmFlexibleType : FlexibleTypeMarker {
val lowerBound: IrSimpleType val lowerBound: IrSimpleType
val upperBound: IrSimpleType val upperBound: IrSimpleType
@@ -64,30 +68,25 @@ private class IrJvmFlexibleTypeImpl(
} }
} }
internal val FLEXIBLE_NULLABILITY_FQN = FqName("kotlin.internal.ir.FlexibleNullability")
internal val FLEXIBLE_MUTABILITY_FQN = FqName("kotlin.internal.ir.FlexibleMutability")
internal val RAW_TYPE_FQN = FqName("kotlin.internal.ir.RawType")
internal fun IrType.isWithFlexibleNullability(): Boolean = internal fun IrType.isWithFlexibleNullability(): Boolean =
hasAnnotation(FLEXIBLE_NULLABILITY_FQN) hasAnnotation(JvmSymbols.FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME)
internal fun IrType.isWithFlexibleMutability(): Boolean = internal fun IrType.isWithFlexibleMutability(): Boolean =
hasAnnotation(FLEXIBLE_MUTABILITY_FQN) hasAnnotation(JvmSymbols.FLEXIBLE_MUTABILITY_ANNOTATION_FQ_NAME)
internal fun IrType.isRaw(): Boolean =
hasAnnotation(RAW_TYPE_FQN)
internal fun IrType.asJvmFlexibleType(builtIns: IrBuiltIns): FlexibleTypeMarker? { internal fun IrType.asJvmFlexibleType(builtIns: IrBuiltIns): FlexibleTypeMarker? {
if (this !is IrSimpleType || annotations.isEmpty()) return null if (this !is IrSimpleType || annotations.isEmpty()) return null
val nullability = isWithFlexibleNullability() val nullability = isWithFlexibleNullability()
val mutability = isWithFlexibleMutability() val mutability = isWithFlexibleMutability()
val raw = isRaw() val raw = isRawType()
if (!nullability && !mutability && !raw) return null if (!nullability && !mutability && !raw) return null
val baseType = this.removeAnnotations { irCtorCall -> val baseType = this.removeAnnotations { irCtorCall ->
val fqName = irCtorCall.type.classFqName val fqName = irCtorCall.type.classFqName
fqName == FLEXIBLE_NULLABILITY_FQN || fqName == FLEXIBLE_MUTABILITY_FQN || fqName == RAW_TYPE_FQN fqName == JvmSymbols.FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME ||
fqName == JvmSymbols.FLEXIBLE_MUTABILITY_ANNOTATION_FQ_NAME ||
fqName == JvmSymbols.RAW_TYPE_ANNOTATION_FQ_NAME
} as IrSimpleType } as IrSimpleType
return IrJvmFlexibleTypeImpl(baseType, builtIns, nullability, mutability, raw) return IrJvmFlexibleTypeImpl(baseType, builtIns, nullability, mutability, raw)
@@ -36,11 +36,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun KotlinTypeMarker.asSimpleType() = this as? SimpleTypeMarker override fun KotlinTypeMarker.asSimpleType() = this as? SimpleTypeMarker
override fun KotlinTypeMarker.asFlexibleType(): FlexibleTypeMarker? = when (this) { override fun KotlinTypeMarker.asFlexibleType(): FlexibleTypeMarker? = this as? FlexibleTypeMarker
is FlexibleTypeMarker -> this
is IrType -> asJvmFlexibleType(irBuiltIns)
else -> null
}
override fun KotlinTypeMarker.isError() = this is IrErrorType override fun KotlinTypeMarker.isError() = this is IrErrorType
@@ -57,7 +53,6 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun FlexibleTypeMarker.upperBound(): SimpleTypeMarker { override fun FlexibleTypeMarker.upperBound(): SimpleTypeMarker {
return when (this) { return when (this) {
is IrDynamicType -> irBuiltIns.anyNType as IrSimpleType is IrDynamicType -> irBuiltIns.anyNType as IrSimpleType
is IrJvmFlexibleType -> this.upperBound
else -> error("Unexpected flexible type ${this::class.java.simpleName}: $this") else -> error("Unexpected flexible type ${this::class.java.simpleName}: $this")
} }
} }
@@ -65,7 +60,6 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker { override fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker {
return when (this) { return when (this) {
is IrDynamicType -> irBuiltIns.nothingType as IrSimpleType is IrDynamicType -> irBuiltIns.nothingType as IrSimpleType
is IrJvmFlexibleType -> this.lowerBound
else -> error("Unexpected flexible type ${this::class.java.simpleName}: $this") else -> error("Unexpected flexible type ${this::class.java.simpleName}: $this")
} }
} }
@@ -76,8 +70,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun SimpleTypeMarker.isMarkedNullable(): Boolean = (this as IrSimpleType).hasQuestionMark override fun SimpleTypeMarker.isMarkedNullable(): Boolean = (this as IrSimpleType).hasQuestionMark
override fun KotlinTypeMarker.isMarkedNullable(): Boolean = override fun KotlinTypeMarker.isMarkedNullable(): Boolean = this is IrSimpleType && hasQuestionMark
this is IrSimpleType && !isWithFlexibleNullability() && hasQuestionMark
override fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker { override fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker {
val simpleType = this as IrSimpleType val simpleType = this as IrSimpleType