[FIR] Add configuring FakeOverrideTypeCalculator into ConeKotlinType.scope

This commit is contained in:
Dmitriy Novozhilov
2020-10-15 12:52:58 +03:00
parent fc23cf76d4
commit 739ebf772c
15 changed files with 153 additions and 43 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.isIteratorNext
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -445,7 +446,7 @@ class Fir2IrVisitor(
private fun ConeKotlinType.doesContainReferencedSymbolInScope(
referencedSymbol: AbstractFirBasedSymbol<*>, name: Name
): Boolean {
val scope = scope(session, components.scopeSession) ?: return false
val scope = scope(session, components.scopeSession, FakeOverrideTypeCalculator.Forced) ?: return false
var result = false
val processor = { it: FirCallableSymbol<*> ->
if (!result && it == referencedSymbol) {
@@ -452,7 +452,7 @@ internal class AdapterGenerator(
return if (argumentType.isBuiltinFunctionalType(session)) {
argumentType.findBaseInvokeSymbol(session, scopeSession)
} else {
argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType)
argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType, shouldCalculateReturnTypesOfFakeOverrides = true)
}?.let {
declarationStorage.getIrFunctionSymbol(it) as? IrSimpleFunctionSymbol
}
@@ -12,7 +12,9 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithFakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
import org.jetbrains.kotlin.fir.scopes.scopeForClass
@@ -22,11 +24,15 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? =
scope(useSiteSession, scopeSession, FirResolvePhase.STATUS)
fun ConeKotlinType.scopeForStatusResolve(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? =
scope(useSiteSession, scopeSession, FirResolvePhase.TYPES)
fun ConeKotlinType.scope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
fakeOverrideTypeCalculator: FakeOverrideTypeCalculator
): FirTypeScope? {
val scope = scope(useSiteSession, scopeSession, FirResolvePhase.STATUS) ?: return null
if (fakeOverrideTypeCalculator == FakeOverrideTypeCalculator.DoNothing) return scope
return FirScopeWithFakeOverrideTypeCalculator(scope, fakeOverrideTypeCalculator)
}
private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession, requiredPhase: FirResolvePhase): FirTypeScope? {
return when (this) {
@@ -260,7 +260,12 @@ private fun argumentTypeWithSuspendConversion(
// We want to check the argument type against non-suspend functional type.
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
if (argumentType.isSubtypeOfFunctionalType(session, expectedFunctionalType)) {
return argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType)?.let { invokeSymbol ->
return argumentType.findContributedInvokeSymbol(
session,
scopeSession,
expectedFunctionalType,
shouldCalculateReturnTypesOfFakeOverrides = false
)?.let { invokeSymbol ->
createFunctionalType(
invokeSymbol.fir.valueParameters.map { it.returnTypeRef.coneType },
null,
@@ -15,6 +15,7 @@ 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.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
import org.jetbrains.kotlin.fir.scopes.scopeForClass
@@ -145,7 +146,7 @@ private fun processConstructors(
is FirTypeAliasSymbol -> {
matchedSymbol.ensureResolved(FirResolvePhase.TYPES, session)
val type = matchedSymbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
val basicScope = type.scope(session, bodyResolveComponents.scopeSession)
val basicScope = type.scope(session, bodyResolveComponents.scopeSession, FakeOverrideTypeCalculator.DoNothing)
if (basicScope != null && type.typeArguments.isNotEmpty()) {
prepareSubstitutingScopeForTypeAliasConstructors(
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.constructType
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -32,7 +33,7 @@ interface ReceiverValue : Receiver {
val receiverExpression: FirExpression
fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? =
type.scope(useSiteSession, scopeSession)
type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
}
// TODO: should inherit just Receiver, not ReceiverValue
@@ -63,7 +64,7 @@ sealed class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
final override var type: ConeKotlinType = type
private set
var implicitScope: FirTypeScope? = type.scope(useSiteSession, scopeSession)
var implicitScope: FirTypeScope? = type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
private set
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? = implicitScope
@@ -87,7 +88,7 @@ sealed class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
typesFromSmartCast = listOf(type)
}
}
implicitScope = type.scope(useSiteSession, scopeSession)
implicitScope = type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
}
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.unwrapSubstitutionOverrides
@@ -119,18 +120,20 @@ private inline fun BodyResolveComponents.resolveSupertypesByMembers(
}
@OptIn(ExperimentalStdlibApi::class)
private fun BodyResolveComponents.getFunctionMembers(type: ConeKotlinType, name: Name): Collection<FirCallableMemberDeclaration<*>> = buildList {
type.scope(session, scopeSession)?.processFunctionsByName(name) {
addIfNotNull(it.fir as? FirSimpleFunction)
private fun BodyResolveComponents.getFunctionMembers(type: ConeKotlinType, name: Name): Collection<FirCallableMemberDeclaration<*>> =
buildList {
type.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing)?.processFunctionsByName(name) {
addIfNotNull(it.fir as? FirSimpleFunction)
}
}
}
@OptIn(ExperimentalStdlibApi::class)
private fun BodyResolveComponents.getPropertyMembers(type: ConeKotlinType, name: Name): Collection<FirCallableMemberDeclaration<*>> = buildList {
type.scope(session, scopeSession)?.processPropertiesByName(name) {
addIfNotNull(it.fir as? FirProperty)
private fun BodyResolveComponents.getPropertyMembers(type: ConeKotlinType, name: Name): Collection<FirCallableMemberDeclaration<*>> =
buildList {
type.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing)?.processPropertiesByName(name) {
addIfNotNull(it.fir as? FirProperty)
}
}
}
private fun BodyResolveComponents.isConcreteMember(supertype: ConeKotlinType, member: FirCallableMemberDeclaration<*>): Boolean {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
@@ -287,9 +288,11 @@ internal open class FirTowerResolveTask(
superTypeRef: FirTypeRef
) {
val scope = when (superTypeRef) {
is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession)
is FirResolvedTypeRef -> superTypeRef.type.scope(session, components.scopeSession, FakeOverrideTypeCalculator.DoNothing)
is FirComposedSuperTypeRef -> FirCompositeScope(
superTypeRef.superTypeRefs.mapNotNull { it.type.scope(session, components.scopeSession) }
superTypeRef.superTypeRefs.mapNotNull {
it.type.scope(session, components.scopeSession, FakeOverrideTypeCalculator.DoNothing)
}
)
else -> null
} ?: return
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -86,7 +87,7 @@ class FirTowerResolver(
context: ResolutionContext
): CandidateCollector {
val outerType = components.outerClassManager.outerType(constructedType)
val scope = constructedType.scope(components.session, components.scopeSession) ?: return collector
val scope = constructedType.scope(components.session, components.scopeSession, FakeOverrideTypeCalculator.DoNothing) ?: return collector
val dispatchReceiver =
if (outerType != null)
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
@@ -94,11 +95,17 @@ fun ConeClassLikeType.findBaseInvokeSymbol(session: FirSession, scopeSession: Sc
fun ConeKotlinType.findContributedInvokeSymbol(
session: FirSession,
scopeSession: ScopeSession,
expectedFunctionalType: ConeClassLikeType
expectedFunctionalType: ConeClassLikeType,
shouldCalculateReturnTypesOfFakeOverrides: Boolean
): FirFunctionSymbol<*>? {
val baseInvokeSymbol = expectedFunctionalType.findBaseInvokeSymbol(session, scopeSession) ?: return null
val scope = scope(session, scopeSession) ?: return null
val fakeOverrideTypeCalculator = if (shouldCalculateReturnTypesOfFakeOverrides) {
FakeOverrideTypeCalculator.Forced
} else {
FakeOverrideTypeCalculator.DoNothing
}
val scope = scope(session, scopeSession, fakeOverrideTypeCalculator) ?: return null
var declaredInvoke: FirFunctionSymbol<*>? = null
scope.processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol ->
if (functionSymbol.fir.valueParameters.size == baseInvokeSymbol.fir.valueParameters.size) {
@@ -9,8 +9,6 @@ import org.jetbrains.kotlin.fir.declarations.FirTypedDeclaration
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.ForcedFakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForLocalClass
import org.jetbrains.kotlin.fir.scopes.ForcedFakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -223,7 +223,7 @@ private class ReturnTypeCalculatorWithJump(
val possiblyFirFakeOverrideSymbol = declaration.symbol as PossiblyFirFakeOverrideSymbol<*, *>
val overriddenDeclaration = possiblyFirFakeOverrideSymbol.overriddenSymbol?.fir as FirTypedDeclaration? ?: return@runIf
tryCalculateReturnType(overriddenDeclaration)
return ForcedFakeOverrideTypeCalculator.computeReturnType(declaration)
return FakeOverrideTypeCalculator.Forced.computeReturnType(declaration)
}
return when (val status = implicitBodyResolveComputationSession.getStatus(declaration.symbol)) {
@@ -23,19 +23,19 @@ abstract class FakeOverrideTypeCalculator {
return declaration.returnTypeRef
}
}
}
object ForcedFakeOverrideTypeCalculator : FakeOverrideTypeCalculator() {
override fun computeReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef {
(declaration.returnTypeRef as? FirResolvedTypeRef)?.let { return it }
val (substitutor, baseSymbol) = declaration.attributes.fakeOverrideSubstitution ?: error("")
val baseDeclaration = baseSymbol.fir as FirTypedDeclaration
val baseReturnType = computeReturnType(baseDeclaration).type
declaration.attributes.fakeOverrideSubstitution = null
val coneType = substitutor.substituteOrSelf(baseReturnType)
val returnType = declaration.returnTypeRef.resolvedTypeFromPrototype(coneType)
declaration.replaceReturnTypeRef(returnType)
return returnType
object Forced : FakeOverrideTypeCalculator() {
override fun computeReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef {
(declaration.returnTypeRef as? FirResolvedTypeRef)?.let { return it }
val (substitutor, baseSymbol) = declaration.attributes.fakeOverrideSubstitution ?: error("")
val baseDeclaration = baseSymbol.fir as FirTypedDeclaration
val baseReturnType = computeReturnType(baseDeclaration).type
declaration.attributes.fakeOverrideSubstitution = null
val coneType = substitutor.substituteOrSelf(baseReturnType)
val returnType = declaration.returnTypeRef.resolvedTypeFromPrototype(coneType)
declaration.replaceReturnTypeRef(returnType)
return returnType
}
}
}
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2020 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.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirTypedDeclaration
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.Name
class FirScopeWithFakeOverrideTypeCalculator(
private val delegate: FirTypeScope,
private val fakeOverrideTypeCalculator: FakeOverrideTypeCalculator
) : FirTypeScope() {
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
delegate.processClassifiersByNameWithSubstitution(name, processor)
}
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) {
delegate.processFunctionsByName(name) {
updateReturnType(it.fir)
processor(it)
}
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
delegate.processPropertiesByName(name) {
updateReturnType(it.fir)
processor(it)
}
}
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
delegate.processDeclaredConstructors(processor)
}
override fun mayContainName(name: Name): Boolean {
return delegate.mayContainName(name)
}
override fun processDirectOverriddenFunctionsWithBaseScope(
functionSymbol: FirFunctionSymbol<*>,
processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction
): ProcessorAction {
return delegate.processDirectOverriddenFunctionsWithBaseScope(functionSymbol) { symbol, scope ->
updateReturnType(symbol.fir)
processor(symbol, scope)
}
}
override fun processDirectOverriddenPropertiesWithBaseScope(
propertySymbol: FirPropertySymbol,
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
): ProcessorAction {
return delegate.processDirectOverriddenPropertiesWithBaseScope(propertySymbol) { symbol, scope ->
updateReturnType(symbol.fir)
processor(symbol, scope)
}
}
override fun getCallableNames(): Set<Name> {
return delegate.getCallableNames()
}
override fun getClassifierNames(): Set<Name> {
return delegate.getClassifierNames()
}
private fun updateReturnType(declaration: FirTypedDeclaration) {
if (declaration.origin == FirDeclarationOrigin.FakeOverride || declaration.origin == FirDeclarationOrigin.IntersectionOverride) {
fakeOverrideTypeCalculator.computeReturnType(declaration)
}
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.*
@@ -91,8 +92,11 @@ internal class KtFirScopeProvider(
override fun getTypeScope(type: KtType): KtScope? {
check(type is KtFirType) { "KtFirScopeProvider can only work with KtFirType, but ${type::class} was provided" }
val firSession = firResolveState.rootModuleSession
val firTypeScope = type.coneType.scope(firSession, firResolveState.firTransformerProvider.getScopeSession(firSession))
?: return null
val firTypeScope = type.coneType.scope(
firSession,
firResolveState.firTransformerProvider.getScopeSession(firSession),
FakeOverrideTypeCalculator.Forced
) ?: return null
return convertToKtScope(firTypeScope)
}