Fix IR types in JVM_IR BridgeLowering
Properly implement the java erasure rules on IrTypes and fix the types for dispatch and extension receivers.
This commit is contained in:
committed by
max-kammerer
parent
c885cadde4
commit
2da0315d2e
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* 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.backend.jvm.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||||
|
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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the erased class for this type parameter according to the java erasure rules.
|
||||||
|
*/
|
||||||
|
val IrTypeParameter.erasedUpperBound: IrClass
|
||||||
|
get() {
|
||||||
|
// Pick the (necessarily unique) non-interface upper bound if it exists
|
||||||
|
for (type in superTypes) {
|
||||||
|
val irClass = type.classOrNull?.owner ?: continue
|
||||||
|
if (!irClass.isJvmInterface) return irClass
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, choose either the first IrClass supertype or recurse.
|
||||||
|
// In the first case, all supertypes are interface types and the choice was arbitrary.
|
||||||
|
// In the second case, there is only a single supertype.
|
||||||
|
return superTypes.first().erasedUpperBound
|
||||||
|
}
|
||||||
|
|
||||||
|
val IrType.erasedUpperBound: IrClass
|
||||||
|
get() = when (val classifier = classifierOrNull) {
|
||||||
|
is IrClassSymbol -> classifier.owner
|
||||||
|
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
+8
-26
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.backend.common.lower.irNot
|
|||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
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.ir.erasedUpperBound
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
@@ -30,20 +31,14 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.defaultType
|
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
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.name.Name
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
@@ -278,9 +273,9 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass
|
|||||||
superQualifierSymbol = if (invokeStatically) maybeOrphanedTarget.parentAsClass.symbol else null
|
superQualifierSymbol = if (invokeStatically) maybeOrphanedTarget.parentAsClass.symbol else null
|
||||||
).apply {
|
).apply {
|
||||||
passTypeArgumentsFrom(this@createBridgeBody)
|
passTypeArgumentsFrom(this@createBridgeBody)
|
||||||
dispatchReceiver = irImplicitCast(irGet(dispatchReceiverParameter!!), dispatchReceiverParameter!!.type)
|
dispatchReceiver = irGet(dispatchReceiverParameter!!)
|
||||||
extensionReceiverParameter?.let {
|
extensionReceiverParameter?.let {
|
||||||
extensionReceiver = irImplicitCast(irGet(it), extensionReceiverParameter!!.type)
|
extensionReceiver = irImplicitCast(irGet(it), maybeOrphanedTarget.extensionReceiverParameter!!.type)
|
||||||
}
|
}
|
||||||
valueParameters.forEach {
|
valueParameters.forEach {
|
||||||
putValueArgument(it.index, irImplicitCast(irGet(it), maybeOrphanedTarget.valueParameters[it.index].type))
|
putValueArgument(it.index, irImplicitCast(irGet(it), maybeOrphanedTarget.valueParameters[it.index].type))
|
||||||
@@ -341,36 +336,23 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass
|
|||||||
// TODO: should be a type mapper functionality.
|
// TODO: should be a type mapper functionality.
|
||||||
private fun IrType.eraseTypeParameters() = when (this) {
|
private fun IrType.eraseTypeParameters() = when (this) {
|
||||||
is IrErrorType -> this
|
is IrErrorType -> this
|
||||||
is IrSimpleType -> {
|
is IrSimpleType ->
|
||||||
val owner = classifier.owner
|
when (val owner = classifier.owner) {
|
||||||
when (owner) {
|
|
||||||
is IrClass -> this
|
is IrClass -> this
|
||||||
is IrTypeParameter -> {
|
is IrTypeParameter -> {
|
||||||
val upperBound = owner.upperBoundClass()
|
val upperBound = owner.erasedUpperBound
|
||||||
IrSimpleTypeImpl(
|
IrSimpleTypeImpl(
|
||||||
upperBound.symbol,
|
upperBound.symbol,
|
||||||
hasQuestionMark,
|
isNullable(),
|
||||||
List(upperBound.typeParameters.size) { IrStarProjectionImpl }, // Should not affect JVM signature, but may result in an invalid type object
|
List(upperBound.typeParameters.size) { IrStarProjectionImpl }, // Should not affect JVM signature, but may result in an invalid type object
|
||||||
owner.annotations
|
owner.annotations
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> error("Unknown IrSimpleType classifier kind: $owner")
|
else -> error("Unknown IrSimpleType classifier kind: $owner")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else -> error("Unknown IrType kind: $this")
|
else -> error("Unknown IrType kind: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrTypeParameter.upperBoundClass(): IrClass {
|
|
||||||
val simpleSuperClassifiers = superTypes.asSequence().filterIsInstance<IrSimpleType>().map { it.classifier }
|
|
||||||
return simpleSuperClassifiers
|
|
||||||
.filterIsInstance<IrClassSymbol>()
|
|
||||||
.let {
|
|
||||||
it.firstOrNull { !it.owner.isInterface } ?: it.firstOrNull()
|
|
||||||
}?.owner ?:
|
|
||||||
simpleSuperClassifiers.filterIsInstance<IrTypeParameterSymbol>().map { it.owner.upperBoundClass() }.firstOrNull() ?:
|
|
||||||
context.irBuiltIns.anyClass.owner
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrSimpleFunction.findAllReachableDeclarations() =
|
private fun IrSimpleFunction.findAllReachableDeclarations() =
|
||||||
findAllReachableDeclarations(FunctionHandleForIrFunction(this)).map { it.irFunction }
|
findAllReachableDeclarations(FunctionHandleForIrFunction(this)).map { it.irFunction }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user