FIR: Rework delegated scope

Now delegated members are generated just to declared scope

^KT-47413 In Progress
This commit is contained in:
Denis.Zharkov
2021-06-29 18:09:12 +03:00
committed by TeamCityServer
parent 082dc3332e
commit a213ee0e01
4 changed files with 198 additions and 56 deletions
@@ -91,7 +91,7 @@ class JavaScopeProvider(
lookupSuperTypes(regularClass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
val superTypeScopes = superTypes.mapNotNull {
it.scopeForSupertype(useSiteSession, scopeSession, subClass = regularClass, declaredScope, delegateFields = null)
it.scopeForSupertype(useSiteSession, scopeSession, subClass = regularClass)
}
JavaClassUseSiteMemberScope(
@@ -10,19 +10,15 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirField
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.CallableId
class FirKotlinScopeProvider(
val declaredMemberScopeDecorator: (
@@ -39,13 +35,21 @@ class FirKotlinScopeProvider(
): FirTypeScope {
return scopeSession.getOrBuild(klass.symbol, USE_SITE) {
val declaredScope = useSiteSession.declaredMemberScope(klass)
val decoratedDeclaredMemberScope =
declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession)
val delegateFields = klass.declarations.filterIsInstance<FirField>().filter { it.isSynthetic }
val decoratedDeclaredMemberScope =
declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession).let {
if (delegateFields.isEmpty())
it
else
FirNewDelegatedMemberScope(useSiteSession, scopeSession, klass, it, delegateFields)
}
val scopes = lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
.mapNotNull { useSiteSuperType ->
useSiteSuperType.scopeForSupertype(useSiteSession, scopeSession, klass, decoratedDeclaredMemberScope, delegateFields)
useSiteSuperType.scopeForSupertype(useSiteSession, scopeSession, klass)
}
FirClassUseSiteMemberScope(
useSiteSession,
@@ -79,8 +83,6 @@ data class ConeSubstitutionScopeKey(
val lookupTag: ConeClassLikeLookupTag, val isFromExpectClass: Boolean, val substitutor: ConeSubstitutor
) : ScopeSessionKey<FirClass, FirClassSubstitutionScope>()
data class DelegatedMemberScopeKey(val callableId: CallableId) : ScopeSessionKey<FirField, FirDelegatedMemberScope>()
fun FirClass.unsubstitutedScope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
@@ -107,25 +109,19 @@ fun ConeKotlinType.scopeForSupertype(
useSiteSession: FirSession,
scopeSession: ScopeSession,
subClass: FirClass,
declaredMemberScope: FirScope,
delegateFields: List<FirField>?,
): FirTypeScope? {
if (this !is ConeClassLikeType) return null
if (this is ConeClassErrorType) return null
val symbol = lookupTag.toSymbol(useSiteSession)
return if (symbol is FirRegularClassSymbol) {
val delegateField = delegateFields?.find {
it.ensureResolved(FirResolvePhase.TYPES, useSiteSession)
useSiteSession.typeContext.equalTypes(it.returnTypeRef.coneType, this)
}
symbol.fir.scopeForSupertype(
symbol.fir.scopeForClassImpl(
substitutor(symbol, this, useSiteSession),
useSiteSession, scopeSession, delegateField,
subClass = subClass,
declaredMemberScope
).let {
it as? FirTypeScope ?: error("$it is expected to be FirOverrideAwareScope")
}
useSiteSession,
scopeSession,
skipPrivateMembers = true,
classFirDispatchReceiver = subClass,
isFromExpectClass = (subClass as? FirRegularClass)?.isExpect == true
)
} else {
null
}
@@ -137,30 +133,6 @@ private fun substitutor(symbol: FirRegularClassSymbol, type: ConeClassLikeType,
return substitutorByMap(originalSubstitution, useSiteSession)
}
fun FirClass.scopeForSupertype(
substitutor: ConeSubstitutor,
useSiteSession: FirSession,
scopeSession: ScopeSession,
delegateField: FirField?,
subClass: FirClass,
declaredMemberScope: FirScope,
): FirTypeScope = scopeForClassImpl(
substitutor,
useSiteSession,
scopeSession,
skipPrivateMembers = true,
classFirDispatchReceiver = subClass,
isFromExpectClass = (subClass as? FirRegularClass)?.isExpect == true
).let {
if (delegateField != null) {
scopeSession.getOrBuild(delegateField, DelegatedMemberScopeKey(delegateField.symbol.callableId)) {
FirDelegatedMemberScope(it, useSiteSession, subClass, delegateField, declaredMemberScope)
}
} else {
it
}
}
private fun FirClass.scopeForClassImpl(
substitutor: ConeSubstitutor,
useSiteSession: FirSession,
@@ -176,7 +148,7 @@ private fun FirClass.scopeForClassImpl(
this, ConeSubstitutionScopeKey(classFirDispatchReceiver.symbol.toLookupTag(), isFromExpectClass, substitutor)
) {
FirClassSubstitutionScope(
useSiteSession, basicScope, substitutor, classFirDispatchReceiver.defaultType(),
useSiteSession, basicScope, substitutor, classFirDispatchReceiver.defaultType(),
skipPrivateMembers, makeExpect = isFromExpectClass
)
}
@@ -0,0 +1,170 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.Name
class FirNewDelegatedMemberScope(
private val session: FirSession,
private val scopeSession: ScopeSession,
private val containingClass: FirClass<*>,
private val declaredMemberScope: FirScope,
private val delegateFields: List<FirField>,
) : FirScope() {
private val dispatchReceiverType = containingClass.defaultType()
private val overrideChecker = FirStandardOverrideChecker(session)
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
declaredMemberScope.processFunctionsByName(name, processor)
val result = mutableListOf<FirNamedFunctionSymbol>()
for (delegateField in delegateFields) {
processFunctionsFromSpecificField(delegateField, name, result)
}
result.forEach(processor)
}
private fun buildScope(delegateField: FirField): FirTypeScope? {
delegateField.ensureResolved(FirResolvePhase.TYPES, session)
return delegateField.returnTypeRef.coneType.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing)
}
private fun processFunctionsFromSpecificField(
delegateField: FirField,
name: Name,
result: MutableList<FirNamedFunctionSymbol>
) {
val scope = buildScope(delegateField) ?: return
scope.processFunctionsByName(name) processor@{ functionSymbol ->
val original = functionSymbol.fir
// KT-6014: If the original is abstract, we still need a delegation
// For example,
// interface IBase { override fun toString(): String }
// object BaseImpl : IBase { override fun toString(): String = ... }
// class Test : IBase by BaseImpl
if (original.isPublicInAny() && original.modality != Modality.ABSTRACT) {
return@processor
}
if (original.modality == Modality.FINAL || original.visibility == Visibilities.Private) {
return@processor
}
if (declaredMemberScope.getFunctions(name).any { overrideChecker.isOverriddenFunction(it.fir, original) }) {
return@processor
}
result.firstOrNull {
overrideChecker.isOverriddenFunction(it.fir, original)
}?.let {
it.fir.multipleDelegatesWithTheSameSignature = true
return@processor
}
val delegatedSymbol =
FirFakeOverrideGenerator.createCopyForFirFunction(
FirNamedFunctionSymbol(
functionSymbol.callableId,
),
original,
session,
FirDeclarationOrigin.Delegated,
newDispatchReceiverType = dispatchReceiverType,
newModality = Modality.OPEN,
).apply {
delegatedWrapperData = DelegatedWrapperData(functionSymbol.fir, containingClass.symbol.toLookupTag(), delegateField)
}.symbol
result += delegatedSymbol
}
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
declaredMemberScope.processPropertiesByName(name, processor)
val result = mutableListOf<FirPropertySymbol>()
for (delegateField in delegateFields) {
processPropertiesFromSpecificField(delegateField, name, result)
}
result.forEach(processor)
}
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
declaredMemberScope.processClassifiersByNameWithSubstitution(name, processor)
}
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
declaredMemberScope.processDeclaredConstructors(processor)
}
private fun processPropertiesFromSpecificField(
delegateField: FirField,
name: Name,
result: MutableList<FirPropertySymbol>
) {
val scope = buildScope(delegateField) ?: return
scope.processPropertiesByName(name) processor@{ propertySymbol ->
if (propertySymbol !is FirPropertySymbol) {
return@processor
}
val original = propertySymbol.fir
if (original.modality == Modality.FINAL || original.visibility == Visibilities.Private) {
return@processor
}
if (declaredMemberScope.getProperties(name)
.any { it is FirPropertySymbol && overrideChecker.isOverriddenProperty(it.fir, original) }
) {
return@processor
}
result.firstOrNull {
overrideChecker.isOverriddenProperty(it.fir, original)
}?.let {
it.fir.multipleDelegatesWithTheSameSignature = true
return@processor
}
val delegatedSymbol =
FirFakeOverrideGenerator.createCopyForFirProperty(
FirPropertySymbol(
propertySymbol.callableId
),
original,
session,
FirDeclarationOrigin.Delegated,
newModality = Modality.OPEN,
newDispatchReceiverType = dispatchReceiverType,
).apply {
delegatedWrapperData = DelegatedWrapperData(propertySymbol.fir, containingClass.symbol.toLookupTag(), delegateField)
}.symbol
result += delegatedSymbol
}
}
}
private object MultipleDelegatesWithTheSameSignatureKey : FirDeclarationDataKey()
var FirCallableDeclaration<*>.multipleDelegatesWithTheSameSignature: Boolean? by FirDeclarationDataRegistry.data(MultipleDelegatesWithTheSameSignatureKey)
@@ -8,7 +8,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Impl modality:FINAL visibility:public superTypes:[<root>.Foo.A; <root>.Foo.B]'
FUN DELEGATED_MEMBER name:add visibility:public modality:OPEN <> ($this:<root>.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean
overridden:
public abstract fun add (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in <root>.Foo.B
public abstract fun add (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in <root>.Foo.A
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -19,7 +19,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
element: GET_VAR 'element: @[FlexibleNullability] kotlin.String? declared in <root>.Impl.add' type=@[FlexibleNullability] kotlin.String? origin=null
FUN DELEGATED_MEMBER name:addAll visibility:public modality:OPEN <> ($this:<root>.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean
overridden:
public abstract fun addAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.B
public abstract fun addAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.A
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>
BLOCK_BODY
@@ -39,7 +39,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
receiver: GET_VAR '<this>: <root>.Impl declared in <root>.Impl.clear' type=<root>.Impl origin=null
FUN DELEGATED_MEMBER name:iterator visibility:public modality:OPEN <> ($this:<root>.Impl) returnType:kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [operator]
overridden:
public abstract fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [fake_override,operator] declared in <root>.Foo.B
public abstract fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [fake_override,operator] declared in <root>.Foo.A
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun iterator (): kotlin.collections.MutableIterator<@[FlexibleNullability] kotlin.String?> [operator] declared in <root>.Impl'
@@ -48,7 +48,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
receiver: GET_VAR '<this>: <root>.Impl declared in <root>.Impl.iterator' type=<root>.Impl origin=null
FUN DELEGATED_MEMBER name:remove visibility:public modality:OPEN <> ($this:<root>.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean
overridden:
public abstract fun remove (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in <root>.Foo.B
public abstract fun remove (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override] declared in <root>.Foo.A
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -59,7 +59,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
element: GET_VAR 'element: @[FlexibleNullability] kotlin.String? declared in <root>.Impl.remove' type=@[FlexibleNullability] kotlin.String? origin=null
FUN DELEGATED_MEMBER name:removeAll visibility:public modality:OPEN <> ($this:<root>.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean
overridden:
public abstract fun removeAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.B
public abstract fun removeAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.A
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>
BLOCK_BODY
@@ -70,7 +70,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
elements: GET_VAR 'elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> declared in <root>.Impl.removeAll' type=kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> origin=null
FUN DELEGATED_MEMBER name:retainAll visibility:public modality:OPEN <> ($this:<root>.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean
overridden:
public abstract fun retainAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.B
public abstract fun retainAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.A
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>
BLOCK_BODY
@@ -81,7 +81,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
elements: GET_VAR 'elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> declared in <root>.Impl.retainAll' type=kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?> origin=null
FUN DELEGATED_MEMBER name:contains visibility:public modality:OPEN <> ($this:<root>.Impl, element:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Boolean [operator]
overridden:
public abstract fun contains (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override,operator] declared in <root>.Foo.B
public abstract fun contains (element: @[FlexibleNullability] kotlin.String?): kotlin.Boolean [fake_override,operator] declared in <root>.Foo.A
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:element index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -92,7 +92,7 @@ FILE fqName:<root> fileName:/DelegationAndInheritanceFromJava.kt
element: GET_VAR 'element: @[FlexibleNullability] kotlin.String? declared in <root>.Impl.contains' type=@[FlexibleNullability] kotlin.String? origin=null
FUN DELEGATED_MEMBER name:containsAll visibility:public modality:OPEN <> ($this:<root>.Impl, elements:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>) returnType:kotlin.Boolean
overridden:
public abstract fun containsAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.B
public abstract fun containsAll (elements: kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>): kotlin.Boolean [fake_override] declared in <root>.Foo.A
$this: VALUE_PARAMETER name:<this> type:<root>.Impl
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<@[FlexibleNullability] kotlin.String?>
BLOCK_BODY