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
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.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -22,7 +26,7 @@ internal object CustomTypeMappers {
*
* 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>()
result += Collection(list, "NSArray")
@@ -43,13 +47,34 @@ internal object CustomTypeMappers {
result += Simple(ClassId.topLevel(string.toSafe()), "NSString")
(0..ObjCExportMapper.maxFunctionTypeParameterCount).forEach {
result += Function(it)
}
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`.
*
@@ -109,8 +134,9 @@ internal object CustomTypeMappers {
}
}
private class Function(parameterCount: Int) : CustomTypeMapper {
override val mappedClassId: ClassId = KotlinBuiltIns.getFunctionClassId(parameterCount)
private class Function(private val parameterCount: Int) : CustomTypeMapper {
override val mappedClassId: ClassId
get() = KotlinBuiltIns.getFunctionClassId(parameterCount)
override fun mapType(mappedSuperType: KotlinType, translator: ObjCExportTranslatorImpl, objCExportScope: ObjCExportScope): ObjCNonNullReferenceType {
return translator.mapFunctionTypeIgnoringNullability(mappedSuperType, objCExportScope, returnsVoid = false)
@@ -756,7 +756,7 @@ internal class ObjCExportTranslatorImpl(
val typeMappingMatches = (listOf(kotlinType) + kotlinType.supertypes()).mapNotNull { type ->
(type.constructor.declarationDescriptor as? ClassDescriptor)?.let { descriptor ->
mapper.customTypeMappers[descriptor.classId]?.let { mapper ->
mapper.getCustomTypeMapper(descriptor)?.let { mapper ->
TypeMappingMatch(type, descriptor, mapper)
}
}
@@ -31,13 +31,14 @@ internal class ObjCExportMapper(
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
fun isSpecialMapped(descriptor: ClassDescriptor): Boolean {
// TODO: this method duplicates some of the [ObjCExportTranslatorImpl.mapReferenceType] logic.
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>()