[FIR] Defer computation of intersection override return type if overridden has implicit return type
#KT-59921
This commit is contained in:
committed by
Space Team
parent
9ec0210c04
commit
1238f081b7
@@ -298,7 +298,7 @@ class JvmMappedScope(
|
||||
newTypeParameters = null,
|
||||
newContextReceiverTypes = emptyList(),
|
||||
isExpect = false,
|
||||
callableCopySubstitutionForTypeUpdater = null,
|
||||
deferredReturnTypeCalculation = null,
|
||||
newSource = oldConstructor.source,
|
||||
)
|
||||
return newSymbol
|
||||
|
||||
+50
-17
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationDataKey
|
||||
@@ -12,7 +13,10 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationDataRegistry
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScopeContext
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
@@ -27,28 +31,46 @@ abstract class CallableCopyTypeCalculator {
|
||||
|
||||
abstract class AbstractCallableCopyTypeCalculator : CallableCopyTypeCalculator() {
|
||||
override fun computeReturnType(declaration: FirCallableDeclaration): FirResolvedTypeRef? {
|
||||
val callableCopySubstitutionForTypeUpdater = declaration.attributes.callableCopySubstitutionForTypeUpdater
|
||||
val callableCopyDeferredTypeCalculation = declaration.attributes.callableCopyDeferredTypeCalculation
|
||||
?: return declaration.getResolvedTypeRef()
|
||||
|
||||
// TODO: drop synchronized in KT-60385
|
||||
synchronized(callableCopySubstitutionForTypeUpdater) {
|
||||
if (declaration.attributes.callableCopySubstitutionForTypeUpdater == null) {
|
||||
synchronized(callableCopyDeferredTypeCalculation) {
|
||||
if (declaration.attributes.callableCopyDeferredTypeCalculation == null) {
|
||||
return declaration.returnTypeRef as FirResolvedTypeRef
|
||||
}
|
||||
|
||||
val (substitutor, baseSymbol) = callableCopySubstitutionForTypeUpdater
|
||||
val baseDeclaration = baseSymbol.fir as FirCallableDeclaration
|
||||
val baseReturnType = computeReturnType(baseDeclaration)?.type ?: return null
|
||||
val coneType = substitutor.substituteOrSelf(baseReturnType)
|
||||
val returnType = declaration.returnTypeRef.resolvedTypeFromPrototype(coneType)
|
||||
declaration.replaceReturnTypeRef(returnType)
|
||||
val returnType = when (callableCopyDeferredTypeCalculation) {
|
||||
is CallableCopySubstitution -> computeSubstitution(callableCopyDeferredTypeCalculation)
|
||||
is CallableCopyIntersection -> computeIntersection(callableCopyDeferredTypeCalculation)
|
||||
} ?: return null
|
||||
val returnTypeRef = declaration.returnTypeRef.resolvedTypeFromPrototype(returnType)
|
||||
|
||||
declaration.replaceReturnTypeRef(returnTypeRef)
|
||||
if (declaration is FirProperty) {
|
||||
declaration.getter?.replaceReturnTypeRef(returnType)
|
||||
declaration.setter?.valueParameters?.firstOrNull()?.replaceReturnTypeRef(returnType)
|
||||
declaration.getter?.replaceReturnTypeRef(returnTypeRef)
|
||||
declaration.setter?.valueParameters?.firstOrNull()?.replaceReturnTypeRef(returnTypeRef)
|
||||
}
|
||||
|
||||
declaration.attributes.callableCopySubstitutionForTypeUpdater = null
|
||||
return returnType
|
||||
declaration.attributes.callableCopyDeferredTypeCalculation = null
|
||||
|
||||
return returnTypeRef
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeSubstitution(callableCopySubstitutionForTypeUpdater: CallableCopySubstitution): ConeKotlinType? {
|
||||
val (substitutor, baseSymbol) = callableCopySubstitutionForTypeUpdater
|
||||
val baseDeclaration = baseSymbol.fir as FirCallableDeclaration
|
||||
val baseReturnType = computeReturnType(baseDeclaration)?.type ?: return null
|
||||
val coneType = substitutor.substituteOrSelf(baseReturnType)
|
||||
|
||||
return coneType
|
||||
}
|
||||
|
||||
private fun computeIntersection(callableCopyIntersection: CallableCopyIntersection): ConeKotlinType? {
|
||||
val (mostSpecific, session) = callableCopyIntersection
|
||||
return FirTypeIntersectionScopeContext.intersectReturnTypes(mostSpecific, session) {
|
||||
computeReturnType(this)?.type
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,13 +87,24 @@ abstract class CallableCopyTypeCalculator {
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
private object CallableCopySubstitutionKey : FirDeclarationDataKey()
|
||||
private object CallableCopyDeferredReturnTypeCalculationKey : FirDeclarationDataKey()
|
||||
|
||||
var FirDeclarationAttributes.callableCopySubstitutionForTypeUpdater: CallableCopySubstitution? by FirDeclarationDataRegistry.attributesAccessor(
|
||||
CallableCopySubstitutionKey
|
||||
var FirDeclarationAttributes.callableCopyDeferredTypeCalculation: CallableCopyDeferredReturnTypeCalculation? by FirDeclarationDataRegistry.attributesAccessor(
|
||||
CallableCopyDeferredReturnTypeCalculationKey
|
||||
)
|
||||
|
||||
sealed class CallableCopyDeferredReturnTypeCalculation
|
||||
|
||||
data class CallableCopySubstitution internal constructor(
|
||||
val substitutor: ConeSubstitutor,
|
||||
val baseSymbol: FirBasedSymbol<*>
|
||||
)
|
||||
) : CallableCopyDeferredReturnTypeCalculation()
|
||||
|
||||
data class CallableCopyIntersection internal constructor(
|
||||
val mostSpecific: Collection<FirCallableSymbol<*>>,
|
||||
val session: FirSession,
|
||||
) : CallableCopyDeferredReturnTypeCalculation() {
|
||||
override fun toString(): String {
|
||||
return "CallableCopyIntersection(mostSpecific=$mostSpecific)"
|
||||
}
|
||||
}
|
||||
+26
-25
@@ -20,8 +20,9 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.CallableCopyDeferredReturnTypeCalculation
|
||||
import org.jetbrains.kotlin.fir.scopes.CallableCopySubstitution
|
||||
import org.jetbrains.kotlin.fir.scopes.callableCopySubstitutionForTypeUpdater
|
||||
import org.jetbrains.kotlin.fir.scopes.callableCopyDeferredTypeCalculation
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
@@ -98,7 +99,7 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType,
|
||||
newContextReceiverTypes,
|
||||
newReturnType,
|
||||
callableCopySubstitutionForTypeUpdater = callableCopySubstitutionForTypeUpdater
|
||||
deferredReturnTypeCalculation = callableCopySubstitutionForTypeUpdater
|
||||
).apply {
|
||||
originalForSubstitutionOverrideAttr = baseFunction
|
||||
}
|
||||
@@ -119,7 +120,7 @@ object FirFakeOverrideGenerator {
|
||||
newReturnType: ConeKotlinType? = null,
|
||||
newModality: Modality? = null,
|
||||
newVisibility: Visibility? = null,
|
||||
callableCopySubstitutionForTypeUpdater: CallableCopySubstitution? = null,
|
||||
deferredReturnTypeCalculation: CallableCopyDeferredReturnTypeCalculation? = null,
|
||||
newSource: KtSourceElement? = null,
|
||||
): FirSimpleFunction = buildSimpleFunction {
|
||||
source = newSource ?: derivedClassLookupTag?.toSymbol(session)?.source ?: baseFunction.source
|
||||
@@ -134,7 +135,7 @@ object FirFakeOverrideGenerator {
|
||||
attributes = baseFunction.attributes.copy()
|
||||
typeParameters += configureAnnotationsTypeParametersAndSignature(
|
||||
session, baseFunction, newParameterTypes, newTypeParameters,
|
||||
newReceiverType, newContextReceiverTypes, newReturnType, callableCopySubstitutionForTypeUpdater, newSymbol
|
||||
newReceiverType, newContextReceiverTypes, newReturnType, deferredReturnTypeCalculation, newSymbol
|
||||
).filterIsInstance<FirTypeParameter>()
|
||||
deprecationsProvider = baseFunction.deprecationsProvider
|
||||
}.apply {
|
||||
@@ -153,7 +154,7 @@ object FirFakeOverrideGenerator {
|
||||
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||
newTypeParameters: List<FirTypeParameterRef>?,
|
||||
isExpect: Boolean,
|
||||
callableCopySubstitutionForTypeUpdater: CallableCopySubstitution?,
|
||||
deferredReturnTypeCalculation: CallableCopyDeferredReturnTypeCalculation?,
|
||||
newSource: KtSourceElement? = null,
|
||||
): FirConstructor = buildConstructor {
|
||||
// TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl
|
||||
@@ -179,7 +180,7 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType = null,
|
||||
newContextReceiverTypes,
|
||||
newReturnType,
|
||||
callableCopySubstitutionForTypeUpdater,
|
||||
deferredReturnTypeCalculation,
|
||||
fakeOverrideSymbol
|
||||
)
|
||||
|
||||
@@ -201,7 +202,7 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType: ConeKotlinType?,
|
||||
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||
newReturnType: ConeKotlinType?,
|
||||
callableCopySubstitutionForTypeUpdater: CallableCopySubstitution?,
|
||||
deferredReturnTypeCalculation: CallableCopyDeferredReturnTypeCalculation?,
|
||||
symbolForOverride: FirFunctionSymbol<*>,
|
||||
): List<FirTypeParameterRef> {
|
||||
return when {
|
||||
@@ -213,7 +214,7 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType,
|
||||
newContextReceiverTypes,
|
||||
newReturnType,
|
||||
callableCopySubstitutionForTypeUpdater,
|
||||
deferredReturnTypeCalculation,
|
||||
origin,
|
||||
)
|
||||
emptyList()
|
||||
@@ -253,7 +254,7 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType,
|
||||
newContextReceiverTypes,
|
||||
newReturnType,
|
||||
callableCopySubstitutionForTypeUpdater,
|
||||
deferredReturnTypeCalculation,
|
||||
origin,
|
||||
)
|
||||
newTypeParameters
|
||||
@@ -268,21 +269,21 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType: ConeKotlinType?,
|
||||
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||
newReturnType: ConeKotlinType?,
|
||||
callableCopySubstitutionForTypeUpdater: CallableCopySubstitution?,
|
||||
deferredTypeCalculation: CallableCopyDeferredReturnTypeCalculation?,
|
||||
origin: FirDeclarationOrigin,
|
||||
) {
|
||||
checkStatusIsResolved(baseFunction)
|
||||
annotations += baseFunction.annotations
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val callableCopySubstitutionForTypeUpdater = callableCopySubstitutionForTypeUpdater
|
||||
val deferredTypeCalculation = deferredTypeCalculation
|
||||
?: runIf(baseFunction.returnTypeRef is FirImplicitTypeRef) {
|
||||
CallableCopySubstitution(ConeSubstitutor.Empty, baseFunction.symbol)
|
||||
}
|
||||
|
||||
if (callableCopySubstitutionForTypeUpdater != null) {
|
||||
if (deferredTypeCalculation != null) {
|
||||
returnTypeRef = FirImplicitTypeRefImplWithoutSource
|
||||
attributes.callableCopySubstitutionForTypeUpdater = callableCopySubstitutionForTypeUpdater
|
||||
attributes.callableCopyDeferredTypeCalculation = deferredTypeCalculation
|
||||
} else {
|
||||
returnTypeRef = baseFunction.returnTypeRef.withReplacedReturnType(newReturnType)
|
||||
}
|
||||
@@ -354,7 +355,7 @@ object FirFakeOverrideGenerator {
|
||||
createCopyForFirProperty(
|
||||
symbolForSubstitutionOverride, baseProperty, derivedClassLookupTag, session, origin,
|
||||
isExpect, newDispatchReceiverType, newTypeParameters, newReceiverType, newContextReceiverTypes, newReturnType,
|
||||
callableCopySubstitutionForTypeUpdater = callableCopySubstitutionForTypeUpdater
|
||||
deferredReturnTypeCalculation = callableCopySubstitutionForTypeUpdater
|
||||
).apply {
|
||||
originalForSubstitutionOverrideAttr = baseProperty
|
||||
}
|
||||
@@ -383,7 +384,7 @@ object FirFakeOverrideGenerator {
|
||||
newReturnType: ConeKotlinType? = null,
|
||||
newModality: Modality? = null,
|
||||
newVisibility: Visibility? = null,
|
||||
callableCopySubstitutionForTypeUpdater: CallableCopySubstitution? = null,
|
||||
deferredReturnTypeCalculation: CallableCopyDeferredReturnTypeCalculation? = null,
|
||||
): FirProperty = buildProperty {
|
||||
source = derivedClassLookupTag?.toSymbol(session)?.source ?: baseProperty.source
|
||||
moduleData = session.nullableModuleData ?: baseProperty.moduleData
|
||||
@@ -404,7 +405,7 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType,
|
||||
newContextReceiverTypes,
|
||||
newReturnType,
|
||||
callableCopySubstitutionForTypeUpdater
|
||||
deferredReturnTypeCalculation
|
||||
)
|
||||
deprecationsProvider = baseProperty.deprecationsProvider
|
||||
|
||||
@@ -529,7 +530,7 @@ object FirFakeOverrideGenerator {
|
||||
newReturnType: ConeKotlinType? = null,
|
||||
newModality: Modality? = null,
|
||||
newVisibility: Visibility? = null,
|
||||
callableCopySubstitutionForTypeUpdater: CallableCopySubstitution? = null,
|
||||
deferredReturnTypeCalculation: CallableCopyDeferredReturnTypeCalculation? = null,
|
||||
): FirField = buildField {
|
||||
source = baseField.source
|
||||
moduleData = session.nullableModuleData ?: baseField.moduleData
|
||||
@@ -544,7 +545,7 @@ object FirFakeOverrideGenerator {
|
||||
attributes = baseField.attributes.copy()
|
||||
configureAnnotationsAndSignature(
|
||||
baseField, newReceiverType, newContextReceiverTypes, newReturnType,
|
||||
callableCopySubstitutionForTypeUpdater, updateReceiver = false
|
||||
deferredReturnTypeCalculation, updateReceiver = false
|
||||
)
|
||||
deprecationsProvider = baseField.deprecationsProvider
|
||||
}.apply {
|
||||
@@ -558,12 +559,12 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType: ConeKotlinType?,
|
||||
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||
newReturnType: ConeKotlinType?,
|
||||
callableCopySubstitutionForTypeUpdater: CallableCopySubstitution?,
|
||||
deferredReturnTypeCalculation: CallableCopyDeferredReturnTypeCalculation?,
|
||||
): List<FirTypeParameter> {
|
||||
return when {
|
||||
baseProperty.typeParameters.isEmpty() -> {
|
||||
configureAnnotationsAndSignature(
|
||||
baseProperty, newReceiverType, newContextReceiverTypes, newReturnType, callableCopySubstitutionForTypeUpdater
|
||||
baseProperty, newReceiverType, newContextReceiverTypes, newReturnType, deferredReturnTypeCalculation
|
||||
)
|
||||
emptyList()
|
||||
}
|
||||
@@ -586,7 +587,7 @@ object FirFakeOverrideGenerator {
|
||||
}
|
||||
else -> {
|
||||
configureAnnotationsAndSignature(
|
||||
baseProperty, newReceiverType, newContextReceiverTypes, newReturnType, callableCopySubstitutionForTypeUpdater
|
||||
baseProperty, newReceiverType, newContextReceiverTypes, newReturnType, deferredReturnTypeCalculation
|
||||
)
|
||||
newTypeParameters
|
||||
}
|
||||
@@ -630,21 +631,21 @@ object FirFakeOverrideGenerator {
|
||||
newReceiverType: ConeKotlinType?,
|
||||
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||
newReturnType: ConeKotlinType?,
|
||||
callableCopySubstitutionForTypeUpdater: CallableCopySubstitution?,
|
||||
deferredReturnTypeCalculation: CallableCopyDeferredReturnTypeCalculation?,
|
||||
updateReceiver: Boolean = true,
|
||||
) {
|
||||
checkStatusIsResolved(baseVariable)
|
||||
annotations += baseVariable.annotations
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val callableCopySubstitutionForTypeUpdater = callableCopySubstitutionForTypeUpdater
|
||||
val deferredReturnTypeCalculation = deferredReturnTypeCalculation
|
||||
?: runIf(baseVariable.returnTypeRef is FirImplicitTypeRef) {
|
||||
CallableCopySubstitution(ConeSubstitutor.Empty, baseVariable.symbol)
|
||||
}
|
||||
|
||||
if (callableCopySubstitutionForTypeUpdater != null) {
|
||||
if (deferredReturnTypeCalculation != null) {
|
||||
returnTypeRef = FirImplicitTypeRefImplWithoutSource
|
||||
attributes.callableCopySubstitutionForTypeUpdater = callableCopySubstitutionForTypeUpdater
|
||||
attributes.callableCopyDeferredTypeCalculation = deferredReturnTypeCalculation
|
||||
} else {
|
||||
returnTypeRef = baseVariable.returnTypeRef.withReplacedReturnType(newReturnType)
|
||||
}
|
||||
|
||||
+36
-18
@@ -347,6 +347,7 @@ class FirTypeIntersectionScopeContext(
|
||||
keyFir.name
|
||||
)
|
||||
val newSymbol = FirIntersectionOverrideFunctionSymbol(callableId, overrides)
|
||||
val deferredReturnTypeCalculation = deferredReturnTypeCalculationOrNull(mostSpecific)
|
||||
FirFakeOverrideGenerator.createCopyForFirFunction(
|
||||
newSymbol, keyFir, derivedClassLookupTag = null, session,
|
||||
FirDeclarationOrigin.IntersectionOverride,
|
||||
@@ -354,7 +355,8 @@ class FirTypeIntersectionScopeContext(
|
||||
newModality = newModality,
|
||||
newVisibility = newVisibility,
|
||||
newDispatchReceiverType = dispatchReceiverType,
|
||||
newReturnType = if (!forClassUseSiteScope) intersectReturnTypes(mostSpecific) else null,
|
||||
deferredReturnTypeCalculation = deferredReturnTypeCalculation,
|
||||
newReturnType = if (!forClassUseSiteScope && deferredReturnTypeCalculation == null) intersectReturnTypes(mostSpecific) else null,
|
||||
).apply {
|
||||
originalForIntersectionOverrideAttr = keyFir
|
||||
}
|
||||
@@ -371,7 +373,7 @@ class FirTypeIntersectionScopeContext(
|
||||
mostSpecific,
|
||||
overrides,
|
||||
::FirIntersectionOverridePropertySymbol,
|
||||
) { symbol, fir, returnType ->
|
||||
) { symbol, fir, deferredReturnTypeCalculation, returnType ->
|
||||
FirFakeOverrideGenerator.createCopyForFirProperty(
|
||||
symbol, fir, derivedClassLookupTag = null, session,
|
||||
FirDeclarationOrigin.IntersectionOverride,
|
||||
@@ -379,6 +381,7 @@ class FirTypeIntersectionScopeContext(
|
||||
newModality = newModality,
|
||||
newVisibility = newVisibility,
|
||||
newDispatchReceiverType = dispatchReceiverType,
|
||||
deferredReturnTypeCalculation = deferredReturnTypeCalculation,
|
||||
// If any of the properties are vars and the types are not equal, these declarations are conflicting
|
||||
// anyway and their uses should result in an overload resolution error.
|
||||
newReturnType = returnType
|
||||
@@ -396,7 +399,7 @@ class FirTypeIntersectionScopeContext(
|
||||
mostSpecific,
|
||||
overrides,
|
||||
::FirIntersectionOverrideFieldSymbol
|
||||
) { symbol, fir, returnType ->
|
||||
) { symbol, fir, deferredReturnTypeCalculation, returnType ->
|
||||
FirFakeOverrideGenerator.createCopyForFirField(
|
||||
symbol, fir, derivedClassLookupTag = null, session,
|
||||
FirDeclarationOrigin.IntersectionOverride,
|
||||
@@ -404,6 +407,7 @@ class FirTypeIntersectionScopeContext(
|
||||
newModality = newModality,
|
||||
newVisibility = newVisibility,
|
||||
newDispatchReceiverType = dispatchReceiverType,
|
||||
deferredReturnTypeCalculation = deferredReturnTypeCalculation,
|
||||
// If any of the properties are vars and the types are not equal, these declarations are conflicting
|
||||
// anyway and their uses should result in an overload resolution error.
|
||||
newReturnType = returnType
|
||||
@@ -415,32 +419,46 @@ class FirTypeIntersectionScopeContext(
|
||||
mostSpecific: Collection<FirCallableSymbol<*>>,
|
||||
overrides: Collection<FirCallableSymbol<*>>,
|
||||
createIntersectionOverrideSymbol: (CallableId, Collection<FirCallableSymbol<*>>) -> S,
|
||||
createCopy: (S, F, returnType: ConeKotlinType?) -> F
|
||||
createCopy: (S, F, deferredReturnTypeCalculation: CallableCopyDeferredReturnTypeCalculation?, returnType: ConeKotlinType?) -> F
|
||||
): S {
|
||||
val key = mostSpecific.first() as S
|
||||
val keyFir = key.fir
|
||||
val callableId = CallableId(dispatchReceiverType.classId ?: keyFir.dispatchReceiverClassLookupTagOrNull()?.classId!!, keyFir.name)
|
||||
val newSymbol = createIntersectionOverrideSymbol(callableId, overrides)
|
||||
val newReturnType = runIf(!forClassUseSiteScope && mostSpecific.none { (it as FirVariableSymbol<*>).fir.isVar }) {
|
||||
intersectReturnTypes(mostSpecific)
|
||||
}
|
||||
createCopy(newSymbol, keyFir, newReturnType).apply {
|
||||
val deferredReturnTypeCalculation = deferredReturnTypeCalculationOrNull(mostSpecific)
|
||||
val newReturnType =
|
||||
runIf(!forClassUseSiteScope && mostSpecific.none { (it as FirVariableSymbol<*>).fir.isVar } && deferredReturnTypeCalculation == null) {
|
||||
intersectReturnTypes(mostSpecific)
|
||||
}
|
||||
createCopy(newSymbol, keyFir, deferredReturnTypeCalculation, newReturnType).apply {
|
||||
originalForIntersectionOverrideAttr = keyFir
|
||||
}
|
||||
return newSymbol
|
||||
}
|
||||
|
||||
private fun intersectReturnTypes(overrides: Collection<FirCallableSymbol<*>>): ConeKotlinType? {
|
||||
val key = overrides.first()
|
||||
// Remap type parameters to the first declaration's:
|
||||
// (fun <A, B> foo(): B) & (fun <C, D> foo(): D?) -> (fun <A, B> foo(): B & B?)
|
||||
val substituted = overrides.mapNotNull {
|
||||
val returnType = it.fir.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||
if (it == key) return@mapNotNull returnType
|
||||
val substitutor = buildSubstitutorForOverridesCheck(it.fir, key.fir, session) ?: return@mapNotNull null
|
||||
returnType?.let(substitutor::substituteOrSelf)
|
||||
private fun deferredReturnTypeCalculationOrNull(mostSpecific: Collection<FirCallableSymbol<*>>): CallableCopyIntersection? {
|
||||
return runIf(mostSpecific.any { it.fir.returnTypeRef is FirImplicitTypeRef }) {
|
||||
CallableCopyIntersection(mostSpecific, session)
|
||||
}
|
||||
}
|
||||
|
||||
private fun intersectReturnTypes(overrides: Collection<FirCallableSymbol<*>>): ConeKotlinType? {
|
||||
return intersectReturnTypes(overrides, session) { returnTypeRef.coneType }
|
||||
}
|
||||
|
||||
companion object {
|
||||
inline fun intersectReturnTypes(overrides: Collection<FirCallableSymbol<*>>, session: FirSession, getReturnType: FirCallableDeclaration.() -> ConeKotlinType?): ConeKotlinType? {
|
||||
val key = overrides.first()
|
||||
// Remap type parameters to the first declaration's:
|
||||
// (fun <A, B> foo(): B) & (fun <C, D> foo(): D?) -> (fun <A, B> foo(): B & B?)
|
||||
val substituted = overrides.mapNotNull {
|
||||
val returnType = it.fir.getReturnType() ?: return@mapNotNull null
|
||||
if (it == key) return@mapNotNull returnType
|
||||
val substitutor = buildSubstitutorForOverridesCheck(it.fir, key.fir, session) ?: return@mapNotNull null
|
||||
returnType.let(substitutor::substituteOrSelf)
|
||||
}
|
||||
return if (substituted.isNotEmpty()) session.typeContext.intersectTypes(substituted) else null
|
||||
}
|
||||
return if (substituted.isNotEmpty()) session.typeContext.intersectTypes(substituted) else null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user