[FIR] Create intersection overrides for fields in intersection type scope
^KT-56820 Fixed
This commit is contained in:
committed by
Space Team
parent
4e56079c59
commit
8c6d4a6f4b
+51
-12
@@ -379,6 +379,42 @@ object FirFakeOverrideGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
fun createCopyForFirField(
|
||||
newSymbol: FirFieldSymbol,
|
||||
baseField: FirField,
|
||||
derivedClassLookupTag: ConeClassLikeLookupTag?,
|
||||
session: FirSession,
|
||||
origin: FirDeclarationOrigin,
|
||||
isExpect: Boolean = baseField.isExpect,
|
||||
newDispatchReceiverType: ConeSimpleKotlinType?,
|
||||
newReceiverType: ConeKotlinType? = null,
|
||||
newContextReceiverTypes: List<ConeKotlinType?>? = null,
|
||||
newReturnType: ConeKotlinType? = null,
|
||||
newModality: Modality? = null,
|
||||
newVisibility: Visibility? = null,
|
||||
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
|
||||
): FirField {
|
||||
return buildField {
|
||||
source = baseField.source
|
||||
moduleData = session.moduleData
|
||||
this.origin = origin
|
||||
name = baseField.name
|
||||
isVar = baseField.isVar
|
||||
this.symbol = newSymbol
|
||||
status = baseField.status.copy(newVisibility, newModality, isExpect = isExpect)
|
||||
|
||||
resolvePhase = baseField.resolvePhase
|
||||
dispatchReceiverType = newDispatchReceiverType
|
||||
attributes = baseField.attributes.copy()
|
||||
configureAnnotationsAndSignature(
|
||||
baseField, newReceiverType, newContextReceiverTypes, newReturnType, fakeOverrideSubstitution, updateReceiver = false
|
||||
)
|
||||
deprecationsProvider = baseField.deprecationsProvider
|
||||
}.apply {
|
||||
containingClassForStaticMemberAttr = derivedClassLookupTag.takeIf { shouldOverrideSetContainingClass(baseField) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirPropertyBuilder.configureAnnotationsTypeParametersAndSignature(
|
||||
useSiteSession: FirSession,
|
||||
baseProperty: FirProperty,
|
||||
@@ -452,35 +488,38 @@ object FirFakeOverrideGenerator {
|
||||
return Triple(copiedReceiverType, copiedContextReceiverTypes, Maybe.Value(copiedReturnType))
|
||||
}
|
||||
|
||||
private fun FirPropertyBuilder.configureAnnotationsAndSignature(
|
||||
baseProperty: FirProperty,
|
||||
private fun FirVariableBuilder.configureAnnotationsAndSignature(
|
||||
baseVariable: FirVariable,
|
||||
newReceiverType: ConeKotlinType?,
|
||||
newContextReceiverTypes: List<ConeKotlinType?>?,
|
||||
newReturnType: ConeKotlinType?,
|
||||
fakeOverrideSubstitution: FakeOverrideSubstitution?
|
||||
fakeOverrideSubstitution: FakeOverrideSubstitution?,
|
||||
updateReceiver: Boolean = true
|
||||
) {
|
||||
annotations += baseProperty.annotations
|
||||
annotations += baseVariable.annotations
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val fakeOverrideSubstitution = fakeOverrideSubstitution ?: runIf(baseProperty.returnTypeRef is FirImplicitTypeRef) {
|
||||
FakeOverrideSubstitution(ConeSubstitutor.Empty, baseProperty.symbol)
|
||||
val fakeOverrideSubstitution = fakeOverrideSubstitution ?: runIf(baseVariable.returnTypeRef is FirImplicitTypeRef) {
|
||||
FakeOverrideSubstitution(ConeSubstitutor.Empty, baseVariable.symbol)
|
||||
}
|
||||
|
||||
if (fakeOverrideSubstitution != null) {
|
||||
returnTypeRef = buildImplicitTypeRef()
|
||||
attributes.fakeOverrideSubstitution = fakeOverrideSubstitution
|
||||
} else {
|
||||
returnTypeRef = baseProperty.returnTypeRef.withReplacedReturnType(newReturnType)
|
||||
returnTypeRef = baseVariable.returnTypeRef.withReplacedReturnType(newReturnType)
|
||||
}
|
||||
|
||||
receiverParameter = baseProperty.receiverParameter?.let { receiverParameter ->
|
||||
buildReceiverParameterCopy(receiverParameter) {
|
||||
typeRef = receiverParameter.typeRef.withReplacedConeType(newReceiverType)
|
||||
if (updateReceiver) {
|
||||
receiverParameter = baseVariable.receiverParameter?.let { receiverParameter ->
|
||||
buildReceiverParameterCopy(receiverParameter) {
|
||||
typeRef = receiverParameter.typeRef.withReplacedConeType(newReceiverType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contextReceivers += baseProperty.contextReceivers.zip(
|
||||
newContextReceiverTypes ?: List(baseProperty.contextReceivers.size) { null }
|
||||
contextReceivers += baseVariable.contextReceivers.zip(
|
||||
newContextReceiverTypes ?: List(baseVariable.contextReceivers.size) { null }
|
||||
) { contextReceiver, newType ->
|
||||
buildContextReceiverCopy(contextReceiver) {
|
||||
typeRef = contextReceiver.typeRef.withReplacedConeType(newType)
|
||||
|
||||
+63
-22
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.caches.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@@ -104,7 +106,6 @@ class FirTypeIntersectionScopeContext(
|
||||
return collectIntersectionResultsForCallables(name, FirScope::processFunctionsByName)
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <D : FirCallableSymbol<*>> collectMembersGroupedByScope(
|
||||
name: Name,
|
||||
processCallables: FirScope.(Name, (D) -> Unit) -> Unit
|
||||
@@ -123,7 +124,6 @@ class FirTypeIntersectionScopeContext(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <D : FirCallableSymbol<*>> collectIntersectionResultsForCallables(
|
||||
name: Name,
|
||||
processCallables: FirScope.(Name, (D) -> Unit) -> Unit
|
||||
@@ -200,7 +200,12 @@ class FirTypeIntersectionScopeContext(
|
||||
is FirPropertySymbol ->
|
||||
createIntersectionOverrideProperty(mostSpecificSymbols, extractedOverridesSymbols, newModality, newVisibility)
|
||||
|
||||
else -> throw IllegalStateException("Should not be here")
|
||||
is FirFieldSymbol -> {
|
||||
if (forClassUseSiteScope) error("Can not create intersection override in class scope for field ${key.member}")
|
||||
createIntersectionOverrideField(mostSpecificSymbols, extractedOverridesSymbols, newModality, newVisibility)
|
||||
}
|
||||
|
||||
else -> error("Unsupported symbol type for creating intersection overrides: ${key.member}")
|
||||
}.withScope(key.baseScope)
|
||||
}
|
||||
|
||||
@@ -372,26 +377,62 @@ class FirTypeIntersectionScopeContext(
|
||||
newModality: Modality?,
|
||||
newVisibility: Visibility,
|
||||
): FirPropertySymbol {
|
||||
val key = mostSpecific.first() as FirPropertySymbol
|
||||
return createIntersectionOverrideVariable<FirPropertySymbol, _>(
|
||||
mostSpecific,
|
||||
overrides,
|
||||
::FirIntersectionOverridePropertySymbol,
|
||||
) { symbol, fir, returnType ->
|
||||
FirFakeOverrideGenerator.createCopyForFirProperty(
|
||||
symbol, fir, derivedClassLookupTag = null, session,
|
||||
FirDeclarationOrigin.IntersectionOverride,
|
||||
newModality = newModality,
|
||||
newVisibility = newVisibility,
|
||||
newDispatchReceiverType = dispatchReceiverType,
|
||||
// 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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIntersectionOverrideField(
|
||||
mostSpecific: Collection<FirCallableSymbol<*>>,
|
||||
overrides: Collection<FirCallableSymbol<*>>,
|
||||
newModality: Modality?,
|
||||
newVisibility: Visibility,
|
||||
): FirFieldSymbol {
|
||||
return createIntersectionOverrideVariable<FirFieldSymbol, _>(
|
||||
mostSpecific,
|
||||
overrides,
|
||||
::FirIntersectionOverrideFieldSymbol
|
||||
) { symbol, fir, returnType ->
|
||||
FirFakeOverrideGenerator.createCopyForFirField(
|
||||
symbol, fir, derivedClassLookupTag = null, session,
|
||||
FirDeclarationOrigin.IntersectionOverride,
|
||||
newModality = newModality,
|
||||
newVisibility = newVisibility,
|
||||
newDispatchReceiverType = dispatchReceiverType,
|
||||
// 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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified S : FirVariableSymbol<F>, F : FirVariable> createIntersectionOverrideVariable(
|
||||
mostSpecific: Collection<FirCallableSymbol<*>>,
|
||||
overrides: Collection<FirCallableSymbol<*>>,
|
||||
createIntersectionOverrideSymbol: (CallableId, Collection<FirCallableSymbol<*>>) -> S,
|
||||
createCopy: (S, F, 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 = FirIntersectionOverridePropertySymbol(callableId, overrides)
|
||||
FirFakeOverrideGenerator.createCopyForFirProperty(
|
||||
newSymbol, keyFir, derivedClassLookupTag = null, session,
|
||||
FirDeclarationOrigin.IntersectionOverride,
|
||||
newModality = newModality,
|
||||
newVisibility = newVisibility,
|
||||
newDispatchReceiverType = dispatchReceiverType,
|
||||
// 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 = if (!forClassUseSiteScope && !mostSpecific.any { (it as FirPropertySymbol).fir.isVar })
|
||||
intersectReturnTypes(mostSpecific)
|
||||
else
|
||||
null,
|
||||
).apply {
|
||||
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 {
|
||||
originalForIntersectionOverrideAttr = keyFir
|
||||
}
|
||||
return newSymbol
|
||||
|
||||
Reference in New Issue
Block a user