Avoid relying on 22 max function parameters count in ObjCExport frontend (#3235)

This commit is contained in:
SvyatoslavScherbina
2019-08-02 11:42:37 +03:00
committed by GitHub
parent 226fd310bf
commit e65ae1c9f7
3 changed files with 37 additions and 10 deletions
@@ -6,8 +6,12 @@
package org.jetbrains.kotlin.backend.konan.objcexport package org.jetbrains.kotlin.backend.konan.objcexport
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
@@ -22,7 +26,7 @@ internal object CustomTypeMappers {
* *
* Don't forget to update [hiddenTypes] after adding new one. * Don't forget to update [hiddenTypes] after adding new one.
*/ */
val byClassId: Map<ClassId, CustomTypeMapper> = with(KotlinBuiltIns.FQ_NAMES) { private val predefined: Map<ClassId, CustomTypeMapper> = with(KotlinBuiltIns.FQ_NAMES) {
val result = mutableListOf<CustomTypeMapper>() val result = mutableListOf<CustomTypeMapper>()
result += Collection(list, "NSArray") result += Collection(list, "NSArray")
@@ -43,13 +47,34 @@ internal object CustomTypeMappers {
result += Simple(ClassId.topLevel(string.toSafe()), "NSString") result += Simple(ClassId.topLevel(string.toSafe()), "NSString")
(0..ObjCExportMapper.maxFunctionTypeParameterCount).forEach {
result += Function(it)
}
result.associateBy { it.mappedClassId } result.associateBy { it.mappedClassId }
} }
fun hasMapper(descriptor: ClassDescriptor): Boolean {
// Should be equivalent to `getMapper(descriptor) != null`.
if (descriptor.classId in predefined) return true
if (descriptor.isMappedFunctionClass()) return true
return false
}
fun getMapper(descriptor: ClassDescriptor): CustomTypeMapper? {
val classId = descriptor.classId
predefined[classId]?.let { return it }
if (descriptor.isMappedFunctionClass()) {
// TODO: somewhat hacky, consider using FunctionClassDescriptor.arity later.
val arity = descriptor.declaredTypeParameters.size - 1 // Type parameters include return type.
assert(classId == KotlinBuiltIns.getFunctionClassId(arity))
return Function(arity)
}
return null
}
private fun ClassDescriptor.isMappedFunctionClass() =
this.getFunctionalClassKind() == FunctionClassDescriptor.Kind.Function
/** /**
* Types to be "hidden" during mapping, i.e. represented as `id`. * Types to be "hidden" during mapping, i.e. represented as `id`.
* *
@@ -109,8 +134,9 @@ internal object CustomTypeMappers {
} }
} }
private class Function(parameterCount: Int) : CustomTypeMapper { private class Function(private val parameterCount: Int) : CustomTypeMapper {
override val mappedClassId: ClassId = KotlinBuiltIns.getFunctionClassId(parameterCount) override val mappedClassId: ClassId
get() = KotlinBuiltIns.getFunctionClassId(parameterCount)
override fun mapType(mappedSuperType: KotlinType, translator: ObjCExportTranslatorImpl, objCExportScope: ObjCExportScope): ObjCNonNullReferenceType { override fun mapType(mappedSuperType: KotlinType, translator: ObjCExportTranslatorImpl, objCExportScope: ObjCExportScope): ObjCNonNullReferenceType {
return translator.mapFunctionTypeIgnoringNullability(mappedSuperType, objCExportScope, returnsVoid = false) return translator.mapFunctionTypeIgnoringNullability(mappedSuperType, objCExportScope, returnsVoid = false)
@@ -756,7 +756,7 @@ internal class ObjCExportTranslatorImpl(
val typeMappingMatches = (listOf(kotlinType) + kotlinType.supertypes()).mapNotNull { type -> val typeMappingMatches = (listOf(kotlinType) + kotlinType.supertypes()).mapNotNull { type ->
(type.constructor.declarationDescriptor as? ClassDescriptor)?.let { descriptor -> (type.constructor.declarationDescriptor as? ClassDescriptor)?.let { descriptor ->
mapper.customTypeMappers[descriptor.classId]?.let { mapper -> mapper.getCustomTypeMapper(descriptor)?.let { mapper ->
TypeMappingMatch(type, descriptor, mapper) TypeMappingMatch(type, descriptor, mapper)
} }
} }
@@ -31,13 +31,14 @@ internal class ObjCExportMapper(
val maxFunctionTypeParameterCount get() = KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS val maxFunctionTypeParameterCount get() = KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS
} }
val customTypeMappers: Map<ClassId, CustomTypeMapper> get() = CustomTypeMappers.byClassId fun getCustomTypeMapper(descriptor: ClassDescriptor): CustomTypeMapper? = CustomTypeMappers.getMapper(descriptor)
val hiddenTypes: Set<ClassId> get() = CustomTypeMappers.hiddenTypes val hiddenTypes: Set<ClassId> get() = CustomTypeMappers.hiddenTypes
fun isSpecialMapped(descriptor: ClassDescriptor): Boolean { fun isSpecialMapped(descriptor: ClassDescriptor): Boolean {
// TODO: this method duplicates some of the [ObjCExportTranslatorImpl.mapReferenceType] logic. // TODO: this method duplicates some of the [ObjCExportTranslatorImpl.mapReferenceType] logic.
return KotlinBuiltIns.isAny(descriptor) || return KotlinBuiltIns.isAny(descriptor) ||
descriptor.getAllSuperClassifiers().any { it.classId in customTypeMappers } descriptor.getAllSuperClassifiers().any { it is ClassDescriptor && CustomTypeMappers.hasMapper(it) }
} }
private val methodBridgeCache = mutableMapOf<FunctionDescriptor, MethodBridge>() private val methodBridgeCache = mutableMapOf<FunctionDescriptor, MethodBridge>()