From 8464b15d271e5ffdbdee9d3cb5dd483f42d532c3 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Wed, 8 Sep 2021 23:55:11 +0500 Subject: [PATCH] [K/N][IR] Fix for https://youtrack.jetbrains.com/issue/KT-48559 Aligned SAM conversion lowering with the JVM's one Also refactored other places with erasure --- .../konan/descriptors/DescriptorUtils.kt | 13 ++---- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 3 +- .../backend/konan/lower/BridgesBuilding.kt | 4 +- .../konan/lower/FunctionReferenceLowering.kt | 5 +-- .../konan/lower/TypeOperatorLowering.kt | 40 +++++++++--------- .../backend/konan/optimizations/DFGBuilder.kt | 41 +++++-------------- 6 files changed, 40 insertions(+), 66 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 12144a58acb..f277cd787c8 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.konan.ir.getSuperClassNotAny import org.jetbrains.kotlin.backend.konan.ir.getSuperInterfaces import org.jetbrains.kotlin.backend.konan.llvm.isVoidAsReturnType import org.jetbrains.kotlin.backend.konan.llvm.longName +import org.jetbrains.kotlin.backend.konan.lower.erasedUpperBound import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.ir.IrBuiltIns @@ -19,7 +20,6 @@ import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.constants.StringValue @@ -150,21 +150,14 @@ private fun IrFunction.bridgeDirectionToAt(overriddenFunction: IrFunction, index return if (otherKind == kind) BridgeDirection.NONE else when (kind) { - TypeKind.VOID, TypeKind.REFERENCE -> BridgeDirection(irClass?.erasure(), BridgeDirectionKind.UNBOX) + TypeKind.VOID, TypeKind.REFERENCE -> BridgeDirection(irClass?.erasedUpperBound, BridgeDirectionKind.UNBOX) TypeKind.VALUE_TYPE -> BridgeDirection( - irClass?.erasure().takeIf { otherKind == TypeKind.VOID } /* Otherwise erase to [Any?] */, + irClass?.erasedUpperBound.takeIf { otherKind == TypeKind.VOID } /* Otherwise erase to [Any?] */, BridgeDirectionKind.BOX) TypeKind.ABSENT -> error("TypeKind.ABSENT should be on both sides") } } -private tailrec fun IrType.erasure(): IrClass = - when (val classifier = classifierOrFail) { - is IrClassSymbol -> classifier.owner - is IrTypeParameterSymbol -> classifier.owner.superTypes.first().erasure() - else -> error(classifier) - } - internal class BridgeDirections(private val array: Array) { constructor(irFunction: IrSimpleFunction, overriddenFunction: IrSimpleFunction) : this(Array(ParameterIndex.allParametersCount(irFunction)) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 166005e82a8..29c9af9ab4a 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -1519,7 +1519,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map this + val upperBound = when (val classifier = classifier) { + is IrClassSymbol -> classifier.defaultType is IrTypeParameterSymbol -> { - val upperBound = classifier.owner.superTypes.firstOrNull() - ?: TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}") - - if (this.hasQuestionMark) { - // `T?` - upperBound.erasureForTypeOperation().makeNullable() - } else { - upperBound.erasureForTypeOperation() - } + // Pick the (necessarily unique) non-interface upper bound if it exists + classifier.owner.superTypes.firstOrNull { + it.classOrNull?.owner?.isInterface == false + } ?: + // 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. + classifier.owner.superTypes.first().erasure() } else -> TODO(classifier.toString()) } + + return if (this.hasQuestionMark) + upperBound.makeNullable() + else + upperBound } +internal val IrType.erasedUpperBound get() = this.erasure().getClass() ?: error(this.render()) + internal class TypeOperatorLowering(val context: CommonBackendContext) : FileLoweringPass, IrBuildingTransformer(context) { override fun lower(irFile: IrFile) { irFile.transformChildren(this, null) } - private fun IrType.erasure(): IrType = this.erasureForTypeOperation() - private fun lowerCast(expression: IrTypeOperatorCall): IrExpression { builder.at(expression) val typeOperand = expression.typeOperand.erasure() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt index 979ead4981d..22494eec449 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt @@ -5,18 +5,21 @@ package org.jetbrains.kotlin.backend.konan.optimizations -import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.ir.allParameters import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole import org.jetbrains.kotlin.backend.common.ir.simpleFunctions import org.jetbrains.kotlin.backend.common.peek import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push -import org.jetbrains.kotlin.backend.konan.* -import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions -import org.jetbrains.kotlin.backend.konan.ir.* -import org.jetbrains.kotlin.backend.konan.llvm.computeFunctionName -import org.jetbrains.kotlin.backend.konan.llvm.localHash +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.getInlinedClassNative +import org.jetbrains.kotlin.backend.konan.ir.actualCallee +import org.jetbrains.kotlin.backend.konan.ir.isAny +import org.jetbrains.kotlin.backend.konan.ir.isObjCObjectType +import org.jetbrains.kotlin.backend.konan.ir.isVirtualCall +import org.jetbrains.kotlin.backend.konan.isNonGeneratedAnnotation +import org.jetbrains.kotlin.backend.konan.logMultiple +import org.jetbrains.kotlin.backend.konan.lower.erasedUpperBound import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* @@ -28,9 +31,6 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.util.constructors -import org.jetbrains.kotlin.ir.util.getArguments -import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -566,27 +566,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag ) } - private fun IrType.erasure(): IrType { - if (this !is IrSimpleType) return this - - val classifier = this.classifier - return when (classifier) { - is IrClassSymbol -> this - is IrTypeParameterSymbol -> { - val upperBound = classifier.owner.superTypes.singleOrNull() ?: - TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}") - - if (this.hasQuestionMark) { - // `T?` - upperBound.erasure().makeNullable() - } else { - upperBound.erasure() - } - } - else -> TODO(classifier.toString()) - } - } - private fun expressionToEdge(expression: IrExpression) = expressionToScopedEdge(expression).value private fun expressionToScopedEdge(expression: IrExpression) = @@ -595,7 +574,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag Scoped( DataFlowIR.Edge( it.value, - symbolTable.mapClassReferenceType(expression.typeOperand.erasure().getClass()!!) + symbolTable.mapClassReferenceType(expression.typeOperand.erasedUpperBound) ), it.scope) } else {