[FIR] Improve synthetic functional interfaces support

Rename fictitiousFunctionSymbols -> syntheticFunctionalInterfaceSymbols
Support suspend function interfaces
Add supertypes for KFunction / KSuspendFunction
This commit is contained in:
simon.ogorodnik
2020-01-09 16:38:32 +03:00
committed by Mikhail Glukhikh
parent 573188bdc4
commit ba4163ba02
9 changed files with 72 additions and 41 deletions
@@ -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)
@@ -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
@@ -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>'
@@ -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
@@ -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