Move eraseTypeParameters to IrUtils and use it in PromisedValue.coerce
This commit is contained in:
committed by
Alexander Udalov
parent
3ce0c336bc
commit
41ce88cb9b
+27
-27
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
@@ -81,35 +82,34 @@ fun PromisedValue.discard(): PromisedValue {
|
||||
private val IrType.unboxed: IrType
|
||||
get() = InlineClassAbi.getUnderlyingType(erasedUpperBound)
|
||||
|
||||
fun PromisedValue.coerceInlineClasses(type: Type, irType: IrType, target: Type, irTarget: IrType): PromisedValue? {
|
||||
val isFromTypeInlineClass = irType.erasedUpperBound.isInline
|
||||
val isToTypeInlineClass = irTarget.erasedUpperBound.isInline
|
||||
if (!isFromTypeInlineClass && !isToTypeInlineClass) return null
|
||||
|
||||
val isFromTypeUnboxed = isFromTypeInlineClass && typeMapper.mapType(irType.unboxed) == type
|
||||
val isToTypeUnboxed = isToTypeInlineClass && typeMapper.mapType(irTarget.unboxed) == target
|
||||
|
||||
return when {
|
||||
isFromTypeUnboxed && !isToTypeUnboxed -> object : PromisedValue(codegen, target, irTarget) {
|
||||
override fun materialize() {
|
||||
this@coerceInlineClasses.materialize()
|
||||
// TODO: This is broken for type parameters
|
||||
StackValue.boxInlineClass(irType.toKotlinType(), mv)
|
||||
}
|
||||
}
|
||||
!isFromTypeUnboxed && isToTypeUnboxed -> object : PromisedValue(codegen, target, irTarget) {
|
||||
override fun materialize() {
|
||||
val value = this@coerceInlineClasses.materialized
|
||||
StackValue.unboxInlineClass(value.type, irTarget.toKotlinType(), mv)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
// On materialization, cast the value to a different type.
|
||||
fun PromisedValue.coerce(target: Type, irTarget: IrType): PromisedValue {
|
||||
coerceInlineClasses(type, irType, target, irTarget)?.let { return it }
|
||||
val erasedSourceType = irType.eraseTypeParameters()
|
||||
val erasedTargetType = irTarget.eraseTypeParameters()
|
||||
val isFromTypeInlineClass = erasedSourceType.classOrNull!!.owner.isInline
|
||||
val isToTypeInlineClass = erasedTargetType.classOrNull!!.owner.isInline
|
||||
|
||||
// Coerce inline classes
|
||||
if (isFromTypeInlineClass || isToTypeInlineClass) {
|
||||
val isFromTypeUnboxed = isFromTypeInlineClass && typeMapper.mapType(erasedSourceType.unboxed) == type
|
||||
val isToTypeUnboxed = isToTypeInlineClass && typeMapper.mapType(erasedTargetType.unboxed) == target
|
||||
|
||||
when {
|
||||
isFromTypeUnboxed && !isToTypeUnboxed -> return object : PromisedValue(codegen, target, irTarget) {
|
||||
override fun materialize() {
|
||||
this@coerce.materialize()
|
||||
StackValue.boxInlineClass(erasedSourceType.toKotlinType(), mv)
|
||||
}
|
||||
}
|
||||
!isFromTypeUnboxed && isToTypeUnboxed -> return object : PromisedValue(codegen, target, irTarget) {
|
||||
override fun materialize() {
|
||||
val value = this@coerce.materialized
|
||||
StackValue.unboxInlineClass(value.type, erasedTargetType.toKotlinType(), mv)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return when (type) {
|
||||
// All unsafe coercions between irTypes should use the UnsafeCoerce intrinsic
|
||||
target -> this
|
||||
|
||||
@@ -9,15 +9,46 @@ import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.isFunction
|
||||
import org.jetbrains.kotlin.ir.util.isNullable
|
||||
import org.jetbrains.kotlin.ir.util.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME
|
||||
|
||||
/**
|
||||
* Perform as much type erasure as is significant for JVM signature generation.
|
||||
* Class types are kept as is, while type parameters are replaced with their
|
||||
* erased upper bounds, keeping the nullability information.
|
||||
*
|
||||
* For example, a type parameter `T?` where `T : Any`, `T : Comparable<T>` is
|
||||
* erased to `Any?`.
|
||||
*
|
||||
* Type arguments to the erased upper bound are replaced by `*`, since
|
||||
* recursive erasure could loop. For example, a type parameter
|
||||
* `T : Comparable<T>` is replaced by `Comparable<*>`.
|
||||
*/
|
||||
fun IrType.eraseTypeParameters() = when (this) {
|
||||
is IrErrorType -> this
|
||||
is IrSimpleType ->
|
||||
when (val owner = classifier.owner) {
|
||||
is IrClass -> this
|
||||
is IrTypeParameter -> {
|
||||
val upperBound = owner.erasedUpperBound
|
||||
IrSimpleTypeImpl(
|
||||
upperBound.symbol,
|
||||
isNullable(),
|
||||
List(upperBound.typeParameters.size) { IrStarProjectionImpl }, // Should not affect JVM signature, but may result in an invalid type object
|
||||
owner.annotations
|
||||
)
|
||||
}
|
||||
else -> error("Unknown IrSimpleType classifier kind: $owner")
|
||||
}
|
||||
else -> error("Unknown IrType kind: $this")
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the erased class for this type parameter according to the java erasure rules.
|
||||
*/
|
||||
|
||||
+5
-28
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
@@ -34,12 +34,10 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
@@ -339,27 +337,6 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform type erasure as much as is significant for JVM signature generation. */
|
||||
// TODO: should be a type mapper functionality.
|
||||
private fun IrType.eraseTypeParameters() = when (this) {
|
||||
is IrErrorType -> this
|
||||
is IrSimpleType ->
|
||||
when (val owner = classifier.owner) {
|
||||
is IrClass -> this
|
||||
is IrTypeParameter -> {
|
||||
val upperBound = owner.erasedUpperBound
|
||||
IrSimpleTypeImpl(
|
||||
upperBound.symbol,
|
||||
isNullable(),
|
||||
List(upperBound.typeParameters.size) { IrStarProjectionImpl }, // Should not affect JVM signature, but may result in an invalid type object
|
||||
owner.annotations
|
||||
)
|
||||
}
|
||||
else -> error("Unknown IrSimpleType classifier kind: $owner")
|
||||
}
|
||||
else -> error("Unknown IrType kind: $this")
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.findAllReachableDeclarations() =
|
||||
findAllReachableDeclarations(FunctionHandleForIrFunction(this)).map { it.irFunction }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user