diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt new file mode 100644 index 00000000000..b02c2e80e92 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt @@ -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() + } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt index 5642ba42fc4..93331e042ab 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt @@ -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.jvm.JvmBackendContext 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.Visibilities 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.IrStatementOrigin 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.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.defaultType import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl -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.ir.util.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addToStdlib.safeAs 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 ).apply { passTypeArgumentsFrom(this@createBridgeBody) - dispatchReceiver = irImplicitCast(irGet(dispatchReceiverParameter!!), dispatchReceiverParameter!!.type) + dispatchReceiver = irGet(dispatchReceiverParameter!!) extensionReceiverParameter?.let { - extensionReceiver = irImplicitCast(irGet(it), extensionReceiverParameter!!.type) + extensionReceiver = irImplicitCast(irGet(it), maybeOrphanedTarget.extensionReceiverParameter!!.type) } valueParameters.forEach { 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. private fun IrType.eraseTypeParameters() = when (this) { is IrErrorType -> this - is IrSimpleType -> { - val owner = classifier.owner - when (owner) { + is IrSimpleType -> + when (val owner = classifier.owner) { is IrClass -> this is IrTypeParameter -> { - val upperBound = owner.upperBoundClass() + val upperBound = owner.erasedUpperBound IrSimpleTypeImpl( upperBound.symbol, - hasQuestionMark, + 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 IrTypeParameter.upperBoundClass(): IrClass { - val simpleSuperClassifiers = superTypes.asSequence().filterIsInstance().map { it.classifier } - return simpleSuperClassifiers - .filterIsInstance() - .let { - it.firstOrNull { !it.owner.isInterface } ?: it.firstOrNull() - }?.owner ?: - simpleSuperClassifiers.filterIsInstance().map { it.owner.upperBoundClass() }.firstOrNull() ?: - context.irBuiltIns.anyClass.owner - } - private fun IrSimpleFunction.findAllReachableDeclarations() = findAllReachableDeclarations(FunctionHandleForIrFunction(this)).map { it.irFunction }