[FIR] Improve synthetic functional interfaces support
Rename fictitiousFunctionSymbols -> syntheticFunctionalInterfaceSymbols Support suspend function interfaces Add supertypes for KFunction / KSuspendFunction
This commit is contained in:
committed by
Mikhail Glukhikh
parent
573188bdc4
commit
ba4163ba02
+60
-26
@@ -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<Int, FirRegularClassSymbol>()
|
||||
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<SyntheticFunctionalInterfaceSymbolKey, FirRegularClassSymbol>()
|
||||
|
||||
|
||||
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<FirCallableSymbol<*>> {
|
||||
return allPackageFragments[packageFqName]?.flatMap {
|
||||
it.getTopLevelCallableSymbols(name)
|
||||
|
||||
+5
-5
@@ -12,9 +12,9 @@ FILE: moreSpecificAmbiguousExtensions.kt
|
||||
lval extFun2: R|kotlin/reflect/KFunction2<IB, IB, kotlin/Unit>| = Q|IB|::R|/extFun|
|
||||
}
|
||||
public final fun testWithExpectedType(): R|kotlin/Unit| {
|
||||
lval extFun_AB_A: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2<IA, IB, kotlin/Unit>| = Q|IA|::R|/extFun|
|
||||
lval extFun_AA_B: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2<IA, IA, kotlin/Unit>| = Q|IB|::R|/extFun|
|
||||
lval extFun_BB_A: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2<IB, IB, kotlin/Unit>| = Q|IA|::R|/extFun|
|
||||
lval extFun_BA_B: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2<IB, IA, kotlin/Unit>| = Q|IB|::R|/extFun|
|
||||
lval extFun_BB_B: @R|kotlin/ExtensionFunctionType|() R|kotlin/reflect/KFunction2<IB, IB, kotlin/Unit>| = 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|
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+3
-3
@@ -34,7 +34,7 @@ FILE fqName:<root> fileName:/callableReferenceTypeArguments.kt
|
||||
PROPERTY name:test1 visibility:public modality:FINAL [val]
|
||||
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Function1<kotlin.Int, kotlin.Unit> visibility:private [final,static]
|
||||
EXPRESSION_BODY
|
||||
FUNCTION_REFERENCE 'public final fun topLevel1 <T> (x: T of <root>.topLevel1): kotlin.Unit [inline] declared in <root>' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
||||
FUNCTION_REFERENCE 'public final fun topLevel1 <T> (x: T of <root>.topLevel1): kotlin.Unit [inline] declared in <root>' type=kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit> origin=null
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:kotlin.Function1<kotlin.Int, kotlin.Unit>
|
||||
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val]
|
||||
BLOCK_BODY
|
||||
@@ -43,7 +43,7 @@ FILE fqName:<root> fileName:/callableReferenceTypeArguments.kt
|
||||
PROPERTY name:test2 visibility:public modality:FINAL [val]
|
||||
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Function1<kotlin.collections.List<kotlin.String>, kotlin.Unit> visibility:private [final,static]
|
||||
EXPRESSION_BODY
|
||||
FUNCTION_REFERENCE 'public final fun topLevel2 <T> (x: kotlin.collections.List<T of <root>.topLevel2>): kotlin.Unit [inline] declared in <root>' type=kotlin.Function1<kotlin.collections.List<kotlin.String>, kotlin.Unit> origin=null
|
||||
FUNCTION_REFERENCE 'public final fun topLevel2 <T> (x: kotlin.collections.List<T of <root>.topLevel2>): kotlin.Unit [inline] declared in <root>' type=kotlin.reflect.KFunction1<kotlin.collections.List<kotlin.String>, kotlin.Unit> origin=null
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test2> visibility:public modality:FINAL <> () returnType:kotlin.Function1<kotlin.collections.List<kotlin.String>, kotlin.Unit>
|
||||
correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val]
|
||||
BLOCK_BODY
|
||||
@@ -52,7 +52,7 @@ FILE fqName:<root> fileName:/callableReferenceTypeArguments.kt
|
||||
PROPERTY name:test3 visibility:public modality:FINAL [val]
|
||||
FIELD PROPERTY_BACKING_FIELD name:test3 type:kotlin.Function1<kotlin.Int, kotlin.Unit> visibility:private [final,static]
|
||||
EXPRESSION_BODY
|
||||
FUNCTION_REFERENCE 'public final fun objectMember <T> (x: T of <root>.Host.objectMember): kotlin.Unit [inline] declared in <root>.Host' type=kotlin.Function1<kotlin.Int, kotlin.Unit> origin=null
|
||||
FUNCTION_REFERENCE 'public final fun objectMember <T> (x: T of <root>.Host.objectMember): kotlin.Unit [inline] declared in <root>.Host' type=kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit> origin=null
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test3> visibility:public modality:FINAL <> () returnType:kotlin.Function1<kotlin.Int, kotlin.Unit>
|
||||
correspondingProperty: PROPERTY name:test3 visibility:public modality:FINAL [val]
|
||||
BLOCK_BODY
|
||||
|
||||
@@ -19,7 +19,7 @@ FILE fqName:<root> fileName:/samConstructors.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 (): java.lang.Runnable declared in <root>'
|
||||
CALL 'public final fun Runnable (block: kotlin.Function0<kotlin.Unit>): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null
|
||||
block: FUNCTION_REFERENCE 'public final fun foo (): kotlin.Unit declared in <root>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||
block: FUNCTION_REFERENCE 'public final fun foo (): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Unit> origin=null
|
||||
FUN name:test4 visibility:public modality:FINAL <> () returnType:java.util.Comparator<kotlin.Int>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test4 (): java.util.Comparator<kotlin.Int> declared in <root>'
|
||||
|
||||
+1
-1
@@ -91,4 +91,4 @@ FILE fqName:<root> fileName:/samConversionsWithSmartCasts.kt
|
||||
BLOCK_BODY
|
||||
CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit [operator] declared in <root>.J' type=kotlin.Unit origin=null
|
||||
$this: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.J' type=<root>.J origin=null
|
||||
r: FUNCTION_REFERENCE 'public final fun test9 (): kotlin.Unit declared in <root>' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||
r: FUNCTION_REFERENCE 'public final fun test9 (): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Unit> origin=null
|
||||
|
||||
+2
-2
@@ -61,7 +61,7 @@ FILE fqName:<root> fileName:/typeAliasConstructorReference.kt
|
||||
PROPERTY name:test1 visibility:public modality:FINAL [val]
|
||||
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Function1<kotlin.Int, <root>.C> visibility:private [final,static]
|
||||
EXPRESSION_BODY
|
||||
FUNCTION_REFERENCE 'public constructor <init> (x: kotlin.Int) [primary] declared in <root>.C' type=kotlin.Function1<kotlin.Int, <root>.C> origin=null
|
||||
FUNCTION_REFERENCE 'public constructor <init> (x: kotlin.Int) [primary] declared in <root>.C' type=kotlin.reflect.KFunction1<kotlin.Int, <root>.C> origin=null
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:kotlin.Function1<kotlin.Int, <root>.C>
|
||||
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val]
|
||||
BLOCK_BODY
|
||||
@@ -70,7 +70,7 @@ FILE fqName:<root> fileName:/typeAliasConstructorReference.kt
|
||||
PROPERTY name:test2 visibility:public modality:FINAL [val]
|
||||
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Function1<kotlin.Int, <root>.Host.Nested> visibility:private [final,static]
|
||||
EXPRESSION_BODY
|
||||
FUNCTION_REFERENCE 'public constructor <init> (x: kotlin.Int) [primary] declared in <root>.Host.Nested' type=kotlin.Function1<kotlin.Int, <root>.Host.Nested> origin=null
|
||||
FUNCTION_REFERENCE 'public constructor <init> (x: kotlin.Int) [primary] declared in <root>.Host.Nested' type=kotlin.reflect.KFunction1<kotlin.Int, <root>.Host.Nested> origin=null
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test2> visibility:public modality:FINAL <> () returnType:kotlin.Function1<kotlin.Int, <root>.Host.Nested>
|
||||
correspondingProperty: PROPERTY name:test2 visibility:public modality:FINAL [val]
|
||||
BLOCK_BODY
|
||||
|
||||
Reference in New Issue
Block a user