From f40278c03637d0c46e2b2e6ac587dfc33995e6d2 Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Fri, 3 Mar 2023 15:00:40 +0100 Subject: [PATCH] An option to allow out-of-scope type parameters in IrManglerComputer In the lowered IR there are often references to type parameters whose containers are not in the current scope. This is incorrect semantically, but it works in practice due to erasure, so when the mangler is used on the lowered IR, we don't want to crash the compiler. --- .../mangle/BaseKotlinMangleComputer.kt | 7 +++-- .../mangle/ir/IrMangleComputer.kt | 5 ++-- .../closures/closureCapturingGenericParam.kt | 27 ++++++++++++++++++- .../backend/konan/llvm/BinaryInterface.kt | 2 +- .../konan/serialization/KonanMangler.kt | 21 +++++++++++---- 5 files changed, 51 insertions(+), 11 deletions(-) diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/mangle/BaseKotlinMangleComputer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/mangle/BaseKotlinMangleComputer.kt index 6ad7c7fc2bf..d25e0baecd0 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/mangle/BaseKotlinMangleComputer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/mangle/BaseKotlinMangleComputer.kt @@ -19,10 +19,13 @@ import org.jetbrains.kotlin.types.model.* * @param Session An additional context used for type computations. * @property builder A string builder to write the mangled name into. * @property mode The mangle mode. + * @property allowOutOfScopeTypeParameters Whether to throw an exception if the container of a referenced type parameter is not found + * in the current scope. This often happens in the lowered IR and should never happen in the IR emitted by the frontend. */ abstract class BaseKotlinMangleComputer( protected val builder: StringBuilder, - protected val mode: MangleMode + protected val mode: MangleMode, + protected val allowOutOfScopeTypeParameters: Boolean = false, ) : KotlinMangleComputer where Declaration : Any, Type : KotlinTypeMarker, @@ -120,7 +123,7 @@ abstract class BaseKotlinMangleComputer= 0) { + require(allowOutOfScopeTypeParameters || containerIndex >= 0) { "No container found for type parameter '${getTypeParameterName(typeParameter)}' of '${renderDeclaration(parent)}'" } appendSignature(containerIndex) diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/mangle/ir/IrMangleComputer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/mangle/ir/IrMangleComputer.kt index 93ab73d67e6..e586f0369d6 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/mangle/ir/IrMangleComputer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/mangle/ir/IrMangleComputer.kt @@ -22,7 +22,8 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid open class IrMangleComputer( builder: StringBuilder, mode: MangleMode, - protected val compatibleMode: Boolean + protected val compatibleMode: Boolean, + allowOutOfScopeTypeParameters: Boolean = false, ) : BaseKotlinMangleComputer< /*Declaration=*/IrDeclaration, /*Type=*/IrType, @@ -31,7 +32,7 @@ open class IrMangleComputer( /*TypeParameterContainer=*/IrDeclaration, /*FunctionDeclaration=*/IrFunction, /*Session=*/Nothing?, - >(builder, mode) { + >(builder, mode, allowOutOfScopeTypeParameters) { final override fun getTypeSystemContext(session: Nothing?) = object : IrTypeSystemContext { override val irBuiltIns: IrBuiltIns diff --git a/compiler/testData/codegen/box/closures/closureCapturingGenericParam.kt b/compiler/testData/codegen/box/closures/closureCapturingGenericParam.kt index cfd69850bd0..654c52b08aa 100644 --- a/compiler/testData/codegen/box/closures/closureCapturingGenericParam.kt +++ b/compiler/testData/codegen/box/closures/closureCapturingGenericParam.kt @@ -14,7 +14,32 @@ class N(val v: Int) : IntConvertible { override fun toInt() = v } +interface Grouping { + fun keyOf(element: GroupingInputTP): GroupingOutputTP +} + +fun groupingBy(keySelector: (Char) -> GroupingByTP): Grouping { + + fun foo(p0: T, p1: GroupingByTP) {} + + foo(0, keySelector('a')) + + class A(p0: T, p1: GroupingByTP) {} + + A(0, keySelector('a')) + + return object : Grouping { + override fun keyOf(element: Char): GroupingByTP = keySelector(element) + } +} + +class Delft { + fun getComparator(other: DelftTP) = { this == other } +} + fun box(): String { - if (computeSum(arrayOf(N(2), N(14))) != 16) return "Fail" + if (computeSum(arrayOf(N(2), N(14))) != 16) return "Fail1" + + if (groupingBy { it }.keyOf('A') != 'A') return "Fail2" return "OK" } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index 143a74104cc..660c36731f2 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.name.Name // TODO: do not serialize descriptors of non-exported declarations. object KonanBinaryInterface { - private val mangler = object : AbstractKonanIrMangler(true) {} + private val mangler = object : AbstractKonanIrMangler(withReturnType = true, allowOutOfScopeTypeParameters = true) {} private val exportChecker = mangler.getExportChecker(compatibleMode = true) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt index 54194d2ab6f..968c3636f3b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMangler.kt @@ -15,10 +15,14 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.util.hasAnnotation -abstract class AbstractKonanIrMangler(private val withReturnType: Boolean) : IrBasedKotlinManglerImpl() { +abstract class AbstractKonanIrMangler( + private val withReturnType: Boolean, + private val allowOutOfScopeTypeParameters: Boolean = false +) : IrBasedKotlinManglerImpl() { override fun getExportChecker(compatibleMode: Boolean): IrExportCheckerVisitor = KonanIrExportChecker(compatibleMode) - override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): IrMangleComputer = KonanIrManglerComputer(StringBuilder(256), mode, compatibleMode, withReturnType) + override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): IrMangleComputer = + KonanIrManglerComputer(StringBuilder(256), mode, compatibleMode, withReturnType, allowOutOfScopeTypeParameters) override fun IrDeclaration.isPlatformSpecificExport(): Boolean { if (this is IrSimpleFunction) if (isFakeOverride) return false @@ -51,8 +55,15 @@ abstract class AbstractKonanIrMangler(private val withReturnType: Boolean) : IrB override fun IrDeclaration.isPlatformSpecificExported(): Boolean = isPlatformSpecificExport() } - private class KonanIrManglerComputer(builder: StringBuilder, mode: MangleMode, compatibleMode: Boolean, private val withReturnType: Boolean) : IrMangleComputer(builder, mode, compatibleMode) { - override fun copy(newMode: MangleMode): IrMangleComputer = KonanIrManglerComputer(builder, newMode, compatibleMode, withReturnType) + private class KonanIrManglerComputer( + builder: StringBuilder, + mode: MangleMode, + compatibleMode: Boolean, + private val withReturnType: Boolean, + allowOutOfScopeTypeParameters: Boolean, + ) : IrMangleComputer(builder, mode, compatibleMode, allowOutOfScopeTypeParameters) { + override fun copy(newMode: MangleMode): IrMangleComputer = + KonanIrManglerComputer(builder, newMode, compatibleMode, withReturnType, allowOutOfScopeTypeParameters) override fun addReturnType(): Boolean = withReturnType @@ -166,4 +177,4 @@ abstract class AbstractKonanDescriptorMangler : DescriptorBasedKotlinManglerImpl } } -object KonanManglerDesc : AbstractKonanDescriptorMangler() \ No newline at end of file +object KonanManglerDesc : AbstractKonanDescriptorMangler()