Fix KT-47708 in FIR by transferring SAM annotations to synthetic constr.
This commit is contained in:
@@ -39,28 +39,37 @@ import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
abstract class FirSamResolver {
|
||||
abstract fun getFunctionTypeForPossibleSamType(type: ConeKotlinType): ConeKotlinType?
|
||||
abstract fun getSamInfoForPossibleSamType(type: ConeKotlinType): SAMInfo<ConeKotlinType>?
|
||||
abstract fun shouldRunSamConversionForFunction(firFunction: FirFunction): Boolean
|
||||
abstract fun getSamConstructor(firRegularClass: FirRegularClass): FirSimpleFunction?
|
||||
|
||||
fun getFunctionTypeForPossibleSamType(type: ConeKotlinType): ConeKotlinType? =
|
||||
getSamInfoForPossibleSamType(type)?.type
|
||||
}
|
||||
|
||||
private val SAM_PARAMETER_NAME = Name.identifier("function")
|
||||
|
||||
data class SAMInfo<out C : ConeKotlinType>(internal val symbol: FirNamedFunctionSymbol, val type: C)
|
||||
|
||||
class FirSamResolverImpl(
|
||||
private val session: FirSession,
|
||||
private val scopeSession: ScopeSession,
|
||||
private val outerClassManager: FirOuterClassManager? = null,
|
||||
) : FirSamResolver() {
|
||||
private val resolvedFunctionType: NullableMap<FirRegularClass, ConeLookupTagBasedType?> = NullableMap()
|
||||
private val resolvedFunctionType: NullableMap<FirRegularClass, SAMInfo<ConeLookupTagBasedType>?> = NullableMap()
|
||||
private val samConstructorsCache = session.samConstructorStorage.samConstructors
|
||||
|
||||
override fun getFunctionTypeForPossibleSamType(type: ConeKotlinType): ConeKotlinType? {
|
||||
override fun getSamInfoForPossibleSamType(type: ConeKotlinType): SAMInfo<ConeKotlinType>? {
|
||||
return when (type) {
|
||||
is ConeClassLikeType -> getFunctionTypeForPossibleSamType(type.fullyExpandedType(session))
|
||||
is ConeFlexibleType -> ConeFlexibleType(
|
||||
getFunctionTypeForPossibleSamType(type.lowerBound)?.lowerBoundIfFlexible() ?: return null,
|
||||
getFunctionTypeForPossibleSamType(type.upperBound)?.upperBoundIfFlexible() ?: return null,
|
||||
)
|
||||
is ConeFlexibleType -> {
|
||||
val (lowerSymbol, lowerType) = getSamInfoForPossibleSamType(type.lowerBound) ?: return null
|
||||
val (_, upperType) = getSamInfoForPossibleSamType(type.upperBound) ?: return null
|
||||
SAMInfo(
|
||||
lowerSymbol,
|
||||
ConeFlexibleType(lowerType.lowerBoundIfFlexible(), upperType.upperBoundIfFlexible())
|
||||
)
|
||||
}
|
||||
is ConeErrorType, is ConeStubType -> null
|
||||
// TODO: support those types as well
|
||||
is ConeTypeParameterType, is ConeTypeVariableType,
|
||||
@@ -72,14 +81,17 @@ class FirSamResolverImpl(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFunctionTypeForPossibleSamType(type: ConeClassLikeType): ConeLookupTagBasedType? {
|
||||
private fun getFunctionTypeForPossibleSamType(type: ConeClassLikeType): SAMInfo<ConeLookupTagBasedType>? {
|
||||
@OptIn(LookupTagInternals::class)
|
||||
val firRegularClass = type.lookupTag.toFirRegularClass(session) ?: return null
|
||||
|
||||
val unsubstitutedFunctionType = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null
|
||||
val (functionSymbol, unsubstitutedFunctionType) = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null
|
||||
|
||||
if (firRegularClass.typeParameters.isEmpty()) {
|
||||
return unsubstitutedFunctionType.withNullability(ConeNullability.create(type.isMarkedNullable), session.typeContext)
|
||||
return SAMInfo(
|
||||
functionSymbol,
|
||||
unsubstitutedFunctionType.withNullability(ConeNullability.create(type.isMarkedNullable), session.typeContext)
|
||||
)
|
||||
}
|
||||
|
||||
val substitutor =
|
||||
@@ -110,7 +122,7 @@ class FirSamResolverImpl(
|
||||
"Function type should always be ConeLookupTagBasedType, but ${result::class} was found"
|
||||
}
|
||||
|
||||
return result
|
||||
return SAMInfo(functionSymbol, result)
|
||||
}
|
||||
|
||||
override fun getSamConstructor(firRegularClass: FirRegularClass): FirSimpleFunction? {
|
||||
@@ -119,7 +131,7 @@ class FirSamResolverImpl(
|
||||
|
||||
fun buildSamConstructor(classSymbol: FirRegularClassSymbol): FirNamedFunctionSymbol? {
|
||||
val firRegularClass = classSymbol.fir
|
||||
val functionType = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null
|
||||
val (functionSymbol, functionType) = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null
|
||||
|
||||
val classId = firRegularClass.classId
|
||||
val symbol = FirSyntheticFunctionSymbol(
|
||||
@@ -217,19 +229,21 @@ class FirSamResolverImpl(
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
}
|
||||
|
||||
annotations += functionSymbol.annotations
|
||||
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
}.apply {
|
||||
containingClassForStaticMemberAttr = outerClassManager?.outerClass(firRegularClass.symbol)?.toLookupTag()
|
||||
}.symbol
|
||||
}
|
||||
|
||||
private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): ConeLookupTagBasedType? {
|
||||
private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): SAMInfo<ConeLookupTagBasedType>? {
|
||||
return resolvedFunctionType.getOrPut(firRegularClass) {
|
||||
if (!firRegularClass.status.isFun) return@getOrPut null
|
||||
val abstractMethod = firRegularClass.getSingleAbstractMethodOrNull(session, scopeSession) ?: return@getOrPut null
|
||||
// TODO: val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) }
|
||||
|
||||
abstractMethod.getFunctionTypeForAbstractMethod()
|
||||
SAMInfo(abstractMethod.symbol, abstractMethod.getFunctionTypeForAbstractMethod())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ abstract class AbstractConeCallConflictResolver(
|
||||
if (!call.usesSAM) {
|
||||
TypeWithConversion(argumentType)
|
||||
} else {
|
||||
val functionType = samResolver.getFunctionTypeForPossibleSamType(argumentType)?.second
|
||||
val functionType = samResolver.getSamInfoForPossibleSamType(argumentType)?.type
|
||||
if (functionType == null) TypeWithConversion(argumentType)
|
||||
else TypeWithConversion(functionType, argumentType)
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
|
||||
|
||||
// TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!))
|
||||
|
||||
val expectedFunctionType = context.bodyResolveComponents.samResolver.getFunctionTypeForPossibleSamType(candidateExpectedType)
|
||||
val (_, expectedFunctionType) = context.bodyResolveComponents.samResolver.getSamInfoForPossibleSamType(candidateExpectedType)
|
||||
?: return null
|
||||
return runIf(argument.isFunctional(session, scopeSession, expectedFunctionType)) {
|
||||
usesSAM = true
|
||||
|
||||
+10
-13
@@ -589,19 +589,16 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
val firRegularClass =
|
||||
session.symbolProvider.getClassLikeSymbolByClassId(expectedArgumentType.lookupTag.classId)?.fir as? FirRegularClass
|
||||
|
||||
firRegularClass?.let {
|
||||
val functionType = samResolver.getFunctionTypeForPossibleSamType(firRegularClass.defaultType())
|
||||
if (functionType != null) {
|
||||
createFunctionalType(
|
||||
functionType.typeArguments.dropLast(1).map { it as ConeKotlinType },
|
||||
null,
|
||||
functionType.typeArguments.last() as ConeKotlinType,
|
||||
functionType.classId?.relativeClassName?.asString()
|
||||
?.startsWith(FunctionClassKind.SuspendFunction.classNamePrefix) == true
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
firRegularClass?.let answer@{
|
||||
val (_, functionType) = samResolver.getSamInfoForPossibleSamType(firRegularClass.defaultType())
|
||||
?: return@answer null
|
||||
createFunctionalType(
|
||||
functionType.typeArguments.dropLast(1).map { it as ConeKotlinType },
|
||||
null,
|
||||
functionType.typeArguments.last() as ConeKotlinType,
|
||||
functionType.classId?.relativeClassName?.asString()
|
||||
?.startsWith(FunctionClassKind.SuspendFunction.classNamePrefix) == true
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
|
||||
Reference in New Issue
Block a user