From c7412844583c8f4cfe6ba56f1a79fe42228276b0 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Wed, 25 Nov 2020 14:36:18 +0300 Subject: [PATCH] [Commonizer] Stricter processing of forward declarations --- .../descriptors/commonizer/TargetProvider.kt | 11 ++- .../commonizer/core/TypeCommonizer.kt | 75 ++++++++++++++----- .../NativeDistributionModulesProvider.kt | 15 +++- .../konan/NativeSensitiveManifestData.kt | 15 +++- .../mergedtree/CirClassifiersCache.kt | 17 ++++- .../commonizer/mergedtree/CirTreeMerger.kt | 46 +++++++++++- .../descriptors/commonizer/utils/fqName.kt | 3 +- .../core/ExtensionReceiverCommonizerTest.kt | 4 +- .../core/TypeParameterCommonizerTest.kt | 4 +- .../core/TypeParameterListCommonizerTest.kt | 4 +- .../core/ValueParameterCommonizerTest.kt | 6 +- .../core/ValueParameterListCommonizerTest.kt | 6 +- .../descriptors/commonizer/utils/mocks.kt | 33 +++++++- 13 files changed, 189 insertions(+), 50 deletions(-) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/TargetProvider.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/TargetProvider.kt index 5b87fac3811..b3abce353fd 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/TargetProvider.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/TargetProvider.kt @@ -28,7 +28,16 @@ interface BuiltInsProvider { } interface ModulesProvider { - class ModuleInfo(val name: String, val originalLocation: File) + class ModuleInfo( + val name: String, + val originalLocation: File, + val cInteropAttributes: CInteropModuleAttributes? + ) + + class CInteropModuleAttributes( + val mainPackageFqName: String, + val exportForwardDeclarations: Collection + ) fun loadModuleInfos(): Map fun loadModules(): Map diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt index ec2732e0c8a..003a5b38663 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt @@ -8,8 +8,10 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory +import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizedTypeAliasAnswer.Companion.FAILURE_MISSING_IN_SOME_TARGET +import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizedTypeAliasAnswer.Companion.SUCCESS_FROM_DEPENDEE_LIBRARY import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache -import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNodeWithClassId +import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.Variance @@ -66,7 +68,7 @@ private class ClassTypeCommonizer(private val cache: CirClassifiersCache) : Abst isMarkedNullable == next.isMarkedNullable && classId == next.classifierId && outerType.commonizeWith(next.outerType) - && commonizeClassifier(classId) { cache.classNode(classId) }.first + && commonizeClass(classId, cache) && arguments.commonizeWith(next.arguments) } @@ -102,11 +104,11 @@ private class TypeAliasTypeCommonizer(private val cache: CirClassifiersCache) : return false if (commonizedTypeBuilder == null) { - val (commonized, commonClassifier) = commonizeClassifier(typeAliasId) { cache.typeAliasNode(typeAliasId) } - if (!commonized) + val answer = commonizeTypeAlias(typeAliasId, cache) + if (!answer.commonized) return false - commonizedTypeBuilder = when (commonClassifier) { + commonizedTypeBuilder = when (val commonClassifier = answer.commonClassifier) { is CirClass -> CommonizedTypeAliasTypeBuilder.forClass(commonClassifier) is CirTypeAlias -> CommonizedTypeAliasTypeBuilder.forTypeAlias(commonClassifier) null -> CommonizedTypeAliasTypeBuilder.forKnownUnderlyingType(next.underlyingType) @@ -216,26 +218,59 @@ private class TypeArgumentListCommonizer(cache: CirClassifiersCache) : AbstractL singleElementCommonizerFactory = { TypeArgumentCommonizer(cache) } ) -private inline fun commonizeClassifier( - classifierId: ClassId, - classifierNode: (classifierId: ClassId) -> CirNodeWithClassId<*, T>? -): Pair { - if (classifierId.packageFqName.isUnderStandardKotlinPackages) { - /* either class or type alias from Kotlin stdlib */ - return true to null +private fun commonizeClass(classId: ClassId, cache: CirClassifiersCache): Boolean { + val packageFqName = classId.packageFqName + if (packageFqName.isUnderStandardKotlinPackages) { + // The class is from Kotlin stdlib. Already commonized. + return true + } else if (packageFqName.isUnderKotlinNativeSyntheticPackages) { + // C/Obj-C forward declarations are: + // - Either resolved to real classes/interfaces from other interop libraries (which are generated by C-interop tool and + // are known to have modality/visibility/other attributes to successfully pass commonization). + // - Or resolved to the same synthetic classes/interfaces. + // ... and therefore are considered as successfully commonized. + return true } - /* or descriptors themselves can be commonized */ - return when (val node = classifierNode(classifierId)) { + return when (val node = cache.classNode(classId)) { null -> { - // No node means that the class or type alias was not subject for commonization at all, probably it lays - // not in commonized module descriptors but somewhere in their dependencies. - true to null + // No node means that the class was not subject for commonization. + // - Either it is missing in certain targets at all => not commonized. + // - Or it is a known forward declaration => consider it as commonized. + cache.isExportedForwardDeclaration(classId) } else -> { - // If entry is present, then contents (common declaration) should not be null. - val commonClassifier = node.commonDeclaration() - (commonClassifier != null) to commonClassifier + // Common declaration in node is not null -> successfully commonized. + (node.commonDeclaration() != null) } } } + +private fun commonizeTypeAlias(typeAliasId: ClassId, cache: CirClassifiersCache): CommonizedTypeAliasAnswer { + val packageFqName = typeAliasId.packageFqName + if (packageFqName.isUnderStandardKotlinPackages) { + // The type alias is from Kotlin stdlib. Already commonized. + return SUCCESS_FROM_DEPENDEE_LIBRARY + } + + return when (val node = cache.typeAliasNode(typeAliasId)) { + null -> { + // No node means that the type alias was not subject for commonization. It is missing in some target(s) => not commonized. + FAILURE_MISSING_IN_SOME_TARGET + } + else -> { + // Common declaration in node is not null -> successfully commonized. + CommonizedTypeAliasAnswer.create(node.commonDeclaration()) + } + } +} + +private class CommonizedTypeAliasAnswer(val commonized: Boolean, val commonClassifier: CirClassifier?) { + companion object { + val SUCCESS_FROM_DEPENDEE_LIBRARY = CommonizedTypeAliasAnswer(true, null) + val FAILURE_MISSING_IN_SOME_TARGET = CommonizedTypeAliasAnswer(false, null) + + fun create(commonClassifier: CirClassifier?) = + if (commonClassifier != null) CommonizedTypeAliasAnswer(true, commonClassifier) else FAILURE_MISSING_IN_SOME_TARGET + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionModulesProvider.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionModulesProvider.kt index 7104fdd93eb..b2929503f72 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionModulesProvider.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionModulesProvider.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.commonizer.BuiltInsProvider import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider +import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.CInteropModuleAttributes import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo import org.jetbrains.kotlin.descriptors.commonizer.utils.NativeFactories import org.jetbrains.kotlin.descriptors.commonizer.utils.createKotlinNativeForwardDeclarationsModule @@ -36,10 +37,20 @@ internal class NativeDistributionModulesProvider( override fun loadModuleInfos(): Map { return libraries.platformLibs.associate { library -> - val name = library.manifestData.uniqueName + val manifestData = library.manifestData + + val name = manifestData.uniqueName val location = File(library.library.libraryFile.path) - name to ModuleInfo(name, location) + val cInteropAttributes = if (manifestData.isInterop) { + val packageFqName = manifestData.packageFqName + ?: manifestData.shortName?.let { "platform.$it" } + ?: manifestData.uniqueName.substringAfter("platform.").let { "platform.$it" } + + CInteropModuleAttributes(packageFqName, manifestData.exportForwardDeclarations) + } else null + + name to ModuleInfo(name, location, cInteropAttributes) } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeSensitiveManifestData.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeSensitiveManifestData.kt index a9bdb2d776c..3d3ee40a5ef 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeSensitiveManifestData.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeSensitiveManifestData.kt @@ -37,7 +37,7 @@ internal data class NativeSensitiveManifestData( addOptionalProperty(KLIB_PROPERTY_DEPENDS, dependencies.isNotEmpty()) { dependencies.joinToString(separator = " ") } addOptionalProperty(KLIB_PROPERTY_INTEROP, isInterop) { "true" } addOptionalProperty(KLIB_PROPERTY_PACKAGE, packageFqName != null) { packageFqName!! } - addOptionalProperty(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS, exportForwardDeclarations.isNotEmpty()) { + addOptionalProperty(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS, exportForwardDeclarations.isNotEmpty() || isInterop) { exportForwardDeclarations.joinToString(" ") } addOptionalProperty(KLIB_PROPERTY_NATIVE_TARGETS, nativeTargets.isNotEmpty()) { @@ -51,15 +51,22 @@ internal data class NativeSensitiveManifestData( check(uniqueName == other.uniqueName) - // Assumption: It's enough to merge native targets list, other properties can be taken from 'this' manifest. + // Merge algorithm: + // - Unite native target lists. + // - Intersect dependency lists. + // - Boolean and 'isInterop'. + // - If both libs are 'isInterop' then intersect exported forward declaration lists. + // - Other properties can be taken from 'this' manifest. + + val bothAreInterop = isInterop && other.isInterop return NativeSensitiveManifestData( uniqueName = uniqueName, versions = versions, dependencies = (dependencies intersect other.dependencies).toList(), - isInterop = isInterop, + isInterop = bothAreInterop, packageFqName = packageFqName, - exportForwardDeclarations = exportForwardDeclarations, + exportForwardDeclarations = if (bothAreInterop) (exportForwardDeclarations intersect other.exportForwardDeclarations).toList() else emptyList(), nativeTargets = HashSet().apply { addAll(nativeTargets) addAll(other.nativeTargets) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassifiersCache.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassifiersCache.kt index bded9891edc..4b22c5d310c 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassifiersCache.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirClassifiersCache.kt @@ -6,22 +6,35 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree import gnu.trove.THashMap +import gnu.trove.THashSet +import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages import org.jetbrains.kotlin.name.ClassId interface CirClassifiersCache { + fun isExportedForwardDeclaration(classId: ClassId): Boolean + fun classNode(classId: ClassId): CirClassNode? fun typeAliasNode(typeAliasId: ClassId): CirTypeAliasNode? + fun addExportedForwardDeclaration(classId: ClassId) + fun addClassNode(classId: ClassId, node: CirClassNode) fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode) } class DefaultCirClassifiersCache : CirClassifiersCache { + private val exportedForwardDeclarations = THashSet() private val classNodes = THashMap() private val typeAliases = THashMap() - override fun classNode(classId: ClassId): CirClassNode? = classNodes[classId] - override fun typeAliasNode(typeAliasId: ClassId): CirTypeAliasNode? = typeAliases[typeAliasId] + override fun isExportedForwardDeclaration(classId: ClassId) = classId in exportedForwardDeclarations + override fun classNode(classId: ClassId) = classNodes[classId] + override fun typeAliasNode(typeAliasId: ClassId) = typeAliases[typeAliasId] + + override fun addExportedForwardDeclaration(classId: ClassId) { + check(!classId.packageFqName.isUnderKotlinNativeSyntheticPackages) + exportedForwardDeclarations += classId + } override fun addClassNode(classId: ClassId, node: CirClassNode) { val oldNode = classNodes.put(classId, node) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTreeMerger.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTreeMerger.kt index 0fbe40831a9..2164fd37540 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTreeMerger.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/CirTreeMerger.kt @@ -21,6 +21,31 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.NullableLazyValue import org.jetbrains.kotlin.storage.StorageManager +/** + * N.B. Limitations on C/Obj-C interop. + * + * [Case 1]: An interop library with two fragments for two targets. The first fragment has a forward declaration of classifier A. + * The second one has a definition of class A. Both fragments have a top-level callable (ex: function) + * with the same signature that refers to type "A" as its return type. + * + * What will happen: Forward declarations will be ignored during building CIR merged tree. So the node for class A + * will contain CirClass "A" for the second target only. This node will not succeed in commonization, and no common class + * declaration will be produced. As a result the top-level callable will not be commonized, as it refers to the type "A" + * that is not formally commonized. + * + * This is not strictly correct: The classifier "A" exists in both targets though in different form. So if the user + * would write shared source code that uses "A" and the callable, then this code would successfully compile against both targets. + * + * The reason why commonization of such classifiers is not supported yet is that this is quite a rare case that requires + * a complex implementation with potential performance penalty. + * + * [Case 2]: A library with two fragments for two targets. The first fragment is interop. The second one is not. + * Similarly to case 1, the 1st fragment has a forward declaration of a classifier, and the 2nd has a real classifier. + * + * At the moment, this is an exotic case. It could happen if someone tries to commonize an MPP library for Native and non-Native + * targets (which is not supported yet), or a Native library where one fragment is produced via C-interop tool and the other one + * is compiled from Kotlin/Native source code (not sure this should be supported at all). + */ class CirTreeMerger( private val storageManager: StorageManager, private val cache: CirClassifiersCache, @@ -40,7 +65,8 @@ class CirTreeMerger( val commonModuleNames = allModuleInfos.map { it.keys }.reduce { a, b -> a intersect b } parameters.targetProviders.forEachIndexed { targetIndex, targetProvider -> - processTarget(rootNode, targetIndex, targetProvider, commonModuleNames) + val commonModuleInfos = allModuleInfos[targetIndex].filterKeys { it in commonModuleNames } + processTarget(rootNode, targetIndex, targetProvider, commonModuleInfos) parameters.progressLogger?.invoke("Loaded declarations for [${targetProvider.target.name}]") System.gc() } @@ -61,7 +87,7 @@ class CirTreeMerger( rootNode: CirRootNode, targetIndex: Int, targetProvider: TargetProvider, - commonModuleNames: Set + commonModuleInfos: Map ) { rootNode.targetDeclarations[targetIndex] = CirRootFactory.create( targetProvider.target, @@ -73,16 +99,28 @@ class CirTreeMerger( val modules: MutableMap = rootNode.modules moduleDescriptors.forEach { (name, moduleDescriptor) -> - if (name in commonModuleNames) - processModule(modules, targetIndex, moduleDescriptor) + val moduleInfo = commonModuleInfos[name] ?: return@forEach + processModule(modules, targetIndex, moduleInfo, moduleDescriptor) } } private fun processModule( modules: MutableMap, targetIndex: Int, + moduleInfo: ModuleInfo, moduleDescriptor: ModuleDescriptor ) { + moduleInfo.cInteropAttributes?.let { cInteropAttributes -> + val exportForwardDeclarations = cInteropAttributes.exportForwardDeclarations.takeIf { it.isNotEmpty() } ?: return@let + val mainPackageFqName = FqName(cInteropAttributes.mainPackageFqName).intern() + + exportForwardDeclarations.forEach { classFqName -> + // Class has synthetic package FQ name (cnames/objcnames). Need to transfer it to the main package. + val className = Name.identifier(classFqName.substringAfterLast('.')).intern() + cache.addExportedForwardDeclaration(internedClassId(mainPackageFqName, className)) + } + } + val moduleName: Name = moduleDescriptor.name.intern() val moduleNode: CirModuleNode = modules.getOrPut(moduleName) { buildModuleNode(storageManager, size) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt index 297df4f80ed..0bb6100c64a 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt @@ -46,7 +46,8 @@ internal val FqName.isUnderKotlinNativeSyntheticPackages: Boolean internal val FqName.isUnderDarwinPackage: Boolean get() = asString().hasPrefix(DARWIN_PACKAGE) -private fun FqName.hasAnyPrefix(prefixes: List): Boolean = +@Suppress("NOTHING_TO_INLINE") +private inline fun FqName.hasAnyPrefix(prefixes: List): Boolean = asString().let { fqName -> prefixes.any(fqName::hasPrefix) } private fun String.hasPrefix(prefix: String): Boolean { diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ExtensionReceiverCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ExtensionReceiverCommonizerTest.kt index 8e5b7222ba9..430383627cf 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ExtensionReceiverCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ExtensionReceiverCommonizerTest.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.commonizer.cir.CirExtensionReceiver import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirExtensionReceiverFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory -import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE +import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.junit.Test @@ -49,7 +49,7 @@ class ExtensionReceiverCommonizerTest : AbstractCommonizerTest() { - override fun createCommonizer() = TypeParameterCommonizer(EMPTY_CLASSIFIERS_CACHE) + override fun createCommonizer() = TypeParameterCommonizer(MOCK_CLASSIFIERS_CACHE) @Test fun allAreReified() = doTestSuccess( diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeParameterListCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeParameterListCommonizerTest.kt index e8efd055a95..6e6bf48f5b4 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeParameterListCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/TypeParameterListCommonizerTest.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter -import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE +import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS_CACHE import org.junit.Test class TypeParameterListCommonizerTest : AbstractCommonizerTest, List>() { @@ -108,7 +108,7 @@ class TypeParameterListCommonizerTest : AbstractCommonizerTest): List { diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizerTest.kt index bedd1c0dabf..18cebf335d0 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizerTest.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.core.CirTestValueParameter.Companion.areEqual import org.jetbrains.kotlin.descriptors.commonizer.core.TypeCommonizerTest.Companion.areEqual import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache -import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE +import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.name.Name import org.junit.Test @@ -141,10 +141,10 @@ class ValueParameterCommonizerTest : AbstractCommonizerTest, List>() { @@ -150,7 +150,7 @@ class ValueParameterListCommonizerTest : AbstractCommonizerTest?, b: List?): Boolean { if (a === b) @@ -159,7 +159,7 @@ class ValueParameterListCommonizerTest : AbstractCommonizerTest