From ba4163ba02e485688d6832ef47b15809b8d4ee61 Mon Sep 17 00:00:00 2001 From: "simon.ogorodnik" Date: Thu, 9 Jan 2020 16:38:32 +0300 Subject: [PATCH] [FIR] Improve synthetic functional interfaces support Rename fictitiousFunctionSymbols -> syntheticFunctionalInterfaceSymbols Support suspend function interfaces Add supertypes for KFunction / KSuspendFunction --- .../impl/FirLibrarySymbolProviderImpl.kt | 86 +++++++++++++------ .../moreSpecificAmbiguousExtensions.txt | 10 +-- .../box/casts/functions/asFunKSmall.kt | 1 - .../box/casts/functions/reifiedAsFunKSmall.kt | 1 - .../casts/functions/reifiedSafeAsFunKSmall.kt | 1 - .../callableReferenceTypeArguments.fir.txt | 6 +- .../expressions/sam/samConstructors.fir.txt | 2 +- .../sam/samConversionsWithSmartCasts.fir.txt | 2 +- .../typeAliasConstructorReference.fir.txt | 4 +- 9 files changed, 72 insertions(+), 41 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirLibrarySymbolProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirLibrarySymbolProviderImpl.kt index 767c6408985..7a51c1316a0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirLibrarySymbolProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirLibrarySymbolProviderImpl.kt @@ -18,13 +18,14 @@ import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider -import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.constructClassType import org.jetbrains.kotlin.fir.resolve.getOrPut import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.metadata.ProtoBuf @@ -132,17 +133,20 @@ class FirLibrarySymbolProviderImpl(val session: FirSession, val kotlinScopeProvi private val allPackageFragments = loadBuiltIns().groupBy { it.fqName } - private val fictitiousFunctionSymbols = mutableMapOf() + private data class SyntheticFunctionalInterfaceSymbolKey(val kind: FunctionClassDescriptor.Kind, val arity: Int) - override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? { - return allPackageFragments[classId.packageFqName]?.firstNotNullResult { - it.getClassLikeSymbolByFqName(classId) - } ?: with(classId) { + private val syntheticFunctionalInterfaceSymbols = mutableMapOf() + + + private fun FunctionClassDescriptor.Kind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity)) + + private fun trySyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? { + return with(classId) { val className = relativeClassName.asString() val kind = FunctionClassDescriptor.Kind.byClassNamePrefix(packageFqName, className) ?: return@with null val prefix = kind.classNamePrefix val arity = className.substring(prefix.length).toIntOrNull() ?: return null - fictitiousFunctionSymbols.getOrPut(arity) { + syntheticFunctionalInterfaceSymbols.getOrPut(SyntheticFunctionalInterfaceSymbolKey(kind, arity)) { val status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.ABSTRACT).apply { isExpect = false isActual = false @@ -187,7 +191,7 @@ class FirLibrarySymbolProviderImpl(val session: FirSession, val kotlinScopeProvi } ) val name = OperatorNameConventions.INVOKE - val status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.ABSTRACT).apply { + val functionStatus = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.ABSTRACT).apply { isExpect = false isActual = false isOverride = false @@ -196,36 +200,36 @@ class FirLibrarySymbolProviderImpl(val session: FirSession, val kotlinScopeProvi isInline = false isTailRec = false isExternal = false - isSuspend = false + isSuspend = + kind == FunctionClassDescriptor.Kind.SuspendFunction || + kind == FunctionClassDescriptor.Kind.KSuspendFunction } + val typeArguments = typeParameters.map { + FirResolvedTypeRefImpl( + null, + ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) + ) + } + addDeclaration( FirSimpleFunctionImpl( null, this@FirLibrarySymbolProviderImpl.session, - FirResolvedTypeRefImpl( - null, - ConeTypeParameterTypeImpl( - typeParameters.last().symbol.toLookupTag(), - false - ) - ), + typeArguments.last(), null, name, - status, + functionStatus, FirNamedFunctionSymbol(CallableId(packageFqName, relativeClassName, name)) ).apply { resolvePhase = FirResolvePhase.DECLARATIONS - valueParameters += this@klass.typeParameters.dropLast(1).map { typeParameter -> - val name = Name.identifier(typeParameter.name.asString().toLowerCase()) + valueParameters += typeArguments.dropLast(1).mapIndexed { index, typeArgument -> + val parameterName = Name.identifier("p${index + 1}") FirValueParameterImpl( null, this@FirLibrarySymbolProviderImpl.session, - FirResolvedTypeRefImpl( - null, - ConeTypeParameterTypeImpl(typeParameter.symbol.toLookupTag(), false) - ), - name, - FirVariableSymbol(name), + typeArgument, + parameterName, + FirVariableSymbol(parameterName), defaultValue = null, isCrossinline = false, isNoinline = false, @@ -234,13 +238,43 @@ class FirLibrarySymbolProviderImpl(val session: FirSession, val kotlinScopeProvi } } ) - replaceSuperTypeRefs(listOf(session.builtinTypes.anyType)) + + fun createSuperType( + kind: FunctionClassDescriptor.Kind + ): FirResolvedTypeRef { + return FirResolvedTypeRefImpl( + null, + ConeClassLikeLookupTagImpl(kind.classId(arity)) + .constructClassType(typeArguments.map { it.type }.toTypedArray(), isNullable = false) + ) + } + + val superTypes = when (kind) { + + FunctionClassDescriptor.Kind.Function, + FunctionClassDescriptor.Kind.SuspendFunction -> + listOf(session.builtinTypes.anyType) + + FunctionClassDescriptor.Kind.KFunction -> + listOf(createSuperType(FunctionClassDescriptor.Kind.Function)) + FunctionClassDescriptor.Kind.KSuspendFunction -> + listOf(createSuperType(FunctionClassDescriptor.Kind.SuspendFunction)) + } + replaceSuperTypeRefs(superTypes) + } } } } } + + override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? { + return allPackageFragments[classId.packageFqName]?.firstNotNullResult { + it.getClassLikeSymbolByFqName(classId) + } ?: trySyntheticFunctionalInterface(classId) + } + override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List> { return allPackageFragments[packageFqName]?.flatMap { it.getTopLevelCallableSymbols(name) diff --git a/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.txt b/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.txt index 38b26f72fcb..97e0863bd3b 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/callableReferences/fromBasicDiagnosticTests/moreSpecificAmbiguousExtensions.txt @@ -12,9 +12,9 @@ FILE: moreSpecificAmbiguousExtensions.kt lval extFun2: R|kotlin/reflect/KFunction2| = Q|IB|::R|/extFun| } public final fun testWithExpectedType(): R|kotlin/Unit| { - lval extFun_AB_A: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2| = Q|IA|::R|/extFun| - lval extFun_AA_B: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2| = Q|IB|::R|/extFun| - lval extFun_BB_A: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2| = Q|IA|::R|/extFun| - lval extFun_BA_B: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2| = Q|IB|::R|/extFun| - lval extFun_BB_B: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2| = Q|IB|::R|/extFun| + lval extFun_AB_A: R|IA.(IB) -> kotlin/Unit| = Q|IA|::R|/extFun| + lval extFun_AA_B: R|IA.(IA) -> kotlin/Unit| = Q|IB|::R|/extFun| + lval extFun_BB_A: R|IB.(IB) -> kotlin/Unit| = Q|IA|::R|/extFun| + lval extFun_BA_B: R|IB.(IA) -> kotlin/Unit| = Q|IB|::R|/extFun| + lval extFun_BB_B: R|IB.(IB) -> kotlin/Unit| = Q|IB|::R|/extFun| } diff --git a/compiler/testData/codegen/box/casts/functions/asFunKSmall.kt b/compiler/testData/codegen/box/casts/functions/asFunKSmall.kt index eb2f762086f..ba59dbf1e1d 100644 --- a/compiler/testData/codegen/box/casts/functions/asFunKSmall.kt +++ b/compiler/testData/codegen/box/casts/functions/asFunKSmall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS, NATIVE diff --git a/compiler/testData/codegen/box/casts/functions/reifiedAsFunKSmall.kt b/compiler/testData/codegen/box/casts/functions/reifiedAsFunKSmall.kt index e25be303dcf..a7d3bff8ffd 100644 --- a/compiler/testData/codegen/box/casts/functions/reifiedAsFunKSmall.kt +++ b/compiler/testData/codegen/box/casts/functions/reifiedAsFunKSmall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS, NATIVE diff --git a/compiler/testData/codegen/box/casts/functions/reifiedSafeAsFunKSmall.kt b/compiler/testData/codegen/box/casts/functions/reifiedSafeAsFunKSmall.kt index cfedd13c368..522457c0eae 100644 --- a/compiler/testData/codegen/box/casts/functions/reifiedSafeAsFunKSmall.kt +++ b/compiler/testData/codegen/box/casts/functions/reifiedSafeAsFunKSmall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS diff --git a/compiler/testData/ir/irText/expressions/callableReferenceTypeArguments.fir.txt b/compiler/testData/ir/irText/expressions/callableReferenceTypeArguments.fir.txt index a467f0036eb..8ac52eccfa0 100644 --- a/compiler/testData/ir/irText/expressions/callableReferenceTypeArguments.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferenceTypeArguments.fir.txt @@ -34,7 +34,7 @@ FILE fqName: fileName:/callableReferenceTypeArguments.kt PROPERTY name:test1 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Function1 visibility:private [final,static] EXPRESSION_BODY - FUNCTION_REFERENCE 'public final fun topLevel1 (x: T of .topLevel1): kotlin.Unit [inline] declared in ' type=kotlin.Function1 origin=null + FUNCTION_REFERENCE 'public final fun topLevel1 (x: T of .topLevel1): kotlin.Unit [inline] declared in ' type=kotlin.reflect.KFunction1 origin=null FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1 correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val] BLOCK_BODY @@ -43,7 +43,7 @@ FILE fqName: fileName:/callableReferenceTypeArguments.kt PROPERTY name:test2 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Function1, kotlin.Unit> visibility:private [final,static] EXPRESSION_BODY - FUNCTION_REFERENCE 'public final fun topLevel2 (x: kotlin.collections.List.topLevel2>): kotlin.Unit [inline] declared in ' type=kotlin.Function1, kotlin.Unit> origin=null + FUNCTION_REFERENCE 'public final fun topLevel2 (x: kotlin.collections.List.topLevel2>): kotlin.Unit [inline] declared in ' type=kotlin.reflect.KFunction1, kotlin.Unit> origin=null FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1, kotlin.Unit> correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val] BLOCK_BODY @@ -52,7 +52,7 @@ FILE fqName: fileName:/callableReferenceTypeArguments.kt PROPERTY name:test3 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test3 type:kotlin.Function1 visibility:private [final,static] EXPRESSION_BODY - FUNCTION_REFERENCE 'public final fun objectMember (x: T of .Host.objectMember): kotlin.Unit [inline] declared in .Host' type=kotlin.Function1 origin=null + FUNCTION_REFERENCE 'public final fun objectMember (x: T of .Host.objectMember): kotlin.Unit [inline] declared in .Host' type=kotlin.reflect.KFunction1 origin=null FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1 correspondingProperty: PROPERTY name:test3 visibility:public modality:FINAL [val] BLOCK_BODY diff --git a/compiler/testData/ir/irText/expressions/sam/samConstructors.fir.txt b/compiler/testData/ir/irText/expressions/sam/samConstructors.fir.txt index 7ccd6b56c20..a937c757259 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConstructors.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConstructors.fir.txt @@ -19,7 +19,7 @@ FILE fqName: fileName:/samConstructors.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test3 (): java.lang.Runnable declared in ' CALL 'public final fun Runnable (block: kotlin.Function0): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null - block: FUNCTION_REFERENCE 'public final fun foo (): kotlin.Unit declared in ' type=kotlin.Function0 origin=null + block: FUNCTION_REFERENCE 'public final fun foo (): kotlin.Unit declared in ' type=kotlin.reflect.KFunction0 origin=null FUN name:test4 visibility:public modality:FINAL <> () returnType:java.util.Comparator BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test4 (): java.util.Comparator declared in ' diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt index 6216caba4b5..35090a00236 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt @@ -91,4 +91,4 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt BLOCK_BODY CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit [operator] declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r: FUNCTION_REFERENCE 'public final fun test9 (): kotlin.Unit declared in ' type=kotlin.Function0 origin=null + r: FUNCTION_REFERENCE 'public final fun test9 (): kotlin.Unit declared in ' type=kotlin.reflect.KFunction0 origin=null diff --git a/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.fir.txt b/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.fir.txt index 7e1d5a36788..6ab74fb876d 100644 --- a/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.fir.txt +++ b/compiler/testData/ir/irText/expressions/typeAliasConstructorReference.fir.txt @@ -61,7 +61,7 @@ FILE fqName: fileName:/typeAliasConstructorReference.kt PROPERTY name:test1 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Function1.C> visibility:private [final,static] EXPRESSION_BODY - FUNCTION_REFERENCE 'public constructor (x: kotlin.Int) [primary] declared in .C' type=kotlin.Function1.C> origin=null + FUNCTION_REFERENCE 'public constructor (x: kotlin.Int) [primary] declared in .C' type=kotlin.reflect.KFunction1.C> origin=null FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1.C> correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val] BLOCK_BODY @@ -70,7 +70,7 @@ FILE fqName: fileName:/typeAliasConstructorReference.kt PROPERTY name:test2 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Function1.Host.Nested> visibility:private [final,static] EXPRESSION_BODY - FUNCTION_REFERENCE 'public constructor (x: kotlin.Int) [primary] declared in .Host.Nested' type=kotlin.Function1.Host.Nested> origin=null + FUNCTION_REFERENCE 'public constructor (x: kotlin.Int) [primary] declared in .Host.Nested' type=kotlin.reflect.KFunction1.Host.Nested> origin=null FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Function1.Host.Nested> correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val] BLOCK_BODY