FirTypeIntersectionScope: introduce "intersection" fake overrides

This commit is contained in:
Mikhail Glukhikh
2020-07-14 10:43:10 +03:00
parent 5a422b5ef6
commit 7a2ea49399
6 changed files with 59 additions and 43 deletions
@@ -447,8 +447,9 @@ class Fir2IrVisitor(
if (castTypeRef is FirResolvedTypeRef && originalTypeRef is FirResolvedTypeRef) { if (castTypeRef is FirResolvedTypeRef && originalTypeRef is FirResolvedTypeRef) {
val castType = castTypeRef.type val castType = castTypeRef.type
if (castType is ConeIntersectionType) { if (castType is ConeIntersectionType) {
val unwrappedSymbol = (referencedSymbol as? FirCallableSymbol)?.overriddenSymbol ?: referencedSymbol
castType.intersectedTypes.forEach { castType.intersectedTypes.forEach {
if (it.doesContainReferencedSymbolInScope(referencedSymbol, calleeReference.name)) { if (it.doesContainReferencedSymbolInScope(unwrappedSymbol, calleeReference.name)) {
return implicitCastOrExpression(value, it) return implicitCastOrExpression(value, it)
} }
} }
@@ -8,10 +8,15 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirValueParameterBuilder
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
abstract class AbstractFirOverrideScope( abstract class AbstractFirOverrideScope(
val session: FirSession, val session: FirSession,
@@ -58,4 +63,33 @@ abstract class AbstractFirOverrideScope(
return override return override
} }
protected open fun createFunctionCopy(
firSimpleFunction: FirSimpleFunction,
newSymbol: FirNamedFunctionSymbol
): FirSimpleFunctionBuilder =
FirSimpleFunctionBuilder().apply {
source = firSimpleFunction.source
session = firSimpleFunction.session
origin = FirDeclarationOrigin.FakeOverride
returnTypeRef = firSimpleFunction.returnTypeRef
receiverTypeRef = firSimpleFunction.receiverTypeRef
name = firSimpleFunction.name
status = firSimpleFunction.status
symbol = newSymbol
}
protected open fun createValueParameterCopy(parameter: FirValueParameter, newDefaultValue: FirExpression?): FirValueParameterBuilder =
FirValueParameterBuilder().apply {
source = parameter.source
session = parameter.session
origin = FirDeclarationOrigin.FakeOverride
returnTypeRef = parameter.returnTypeRef
name = parameter.name
symbol = FirVariableSymbol(parameter.symbol.callableId)
defaultValue = newDefaultValue
isCrossinline = parameter.isCrossinline
isNoinline = parameter.isNoinline
isVararg = parameter.isVararg
}
} }
@@ -6,13 +6,8 @@
package org.jetbrains.kotlin.fir.scopes.impl package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirValueParameterBuilder
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
@@ -108,35 +103,6 @@ abstract class AbstractFirUseSiteMemberScope(
return newSymbol return newSymbol
} }
protected open fun createFunctionCopy(
firSimpleFunction: FirSimpleFunction,
newSymbol: FirNamedFunctionSymbol
): FirSimpleFunctionBuilder =
FirSimpleFunctionBuilder().apply {
source = firSimpleFunction.source
session = firSimpleFunction.session
origin = FirDeclarationOrigin.FakeOverride
returnTypeRef = firSimpleFunction.returnTypeRef
receiverTypeRef = firSimpleFunction.receiverTypeRef
name = firSimpleFunction.name
status = firSimpleFunction.status
symbol = newSymbol
}
protected open fun createValueParameterCopy(parameter: FirValueParameter, newDefaultValue: FirExpression?): FirValueParameterBuilder =
FirValueParameterBuilder().apply {
source = parameter.source
session = parameter.session
origin = FirDeclarationOrigin.FakeOverride
returnTypeRef = parameter.returnTypeRef
name = parameter.name
symbol = FirVariableSymbol(parameter.symbol.callableId)
defaultValue = newDefaultValue
isCrossinline = parameter.isCrossinline
isNoinline = parameter.isNoinline
isVararg = parameter.isVararg
}
override fun processOverriddenFunctionsWithDepth( override fun processOverriddenFunctionsWithDepth(
functionSymbol: FirFunctionSymbol<*>, functionSymbol: FirFunctionSymbol<*>,
processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction
@@ -91,8 +91,22 @@ class FirTypeIntersectionScope private constructor(
val extractedOverrides = extractBothWaysOverridable(maxByVisibility, allMembers) val extractedOverrides = extractBothWaysOverridable(maxByVisibility, allMembers)
val mostSpecific = selectMostSpecificMember(extractedOverrides) val mostSpecific = selectMostSpecificMember(extractedOverrides)
overriddenSymbols[mostSpecific] = extractedOverrides if (extractedOverrides.size > 1 && mostSpecific is FirNamedFunctionSymbol) {
processor(mostSpecific) // TODO: same code for properties
val newSymbol = FirNamedFunctionSymbol(mostSpecific.callableId, mostSpecific.isFakeOverride, mostSpecific)
val mostSpecificFunction = mostSpecific.fir
createFunctionCopy(mostSpecific.fir, newSymbol).apply {
resolvePhase = mostSpecificFunction.resolvePhase
typeParameters += mostSpecificFunction.typeParameters
valueParameters += mostSpecificFunction.valueParameters
}.build()
overriddenSymbols[newSymbol] = extractedOverrides
@Suppress("UNCHECKED_CAST")
processor(newSymbol as D)
} else {
overriddenSymbols[mostSpecific] = extractedOverrides
processor(mostSpecific)
}
} }
return true return true
@@ -240,12 +254,13 @@ class FirTypeIntersectionScope private constructor(
functionSymbol: FirFunctionSymbol<*>, functionSymbol: FirFunctionSymbol<*>,
processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction
): ProcessorAction { ): ProcessorAction {
for (directOverridden in getDirectOverriddenSymbols(functionSymbol)) { for (overridden in getDirectOverriddenSymbols(functionSymbol)) {
if (!processor(directOverridden, 0)) return ProcessorAction.STOP val overriddenDepth = if (overridden is FirNamedFunctionSymbol && overridden.overriddenSymbol != null) 0 else 1
if (!processor(overridden, overriddenDepth)) return ProcessorAction.STOP
// TODO: Preserve the scope where directOverridden came from // TODO: Preserve the scope where directOverridden came from
for (scope in scopes) { for (scope in scopes) {
if (!scope.processOverriddenFunctionsWithDepth(directOverridden) { symbol, depth -> if (!scope.processOverriddenFunctionsWithDepth(overridden) { symbol, depth ->
processor(symbol, depth) processor(symbol, depth + overriddenDepth)
} }
) return ProcessorAction.STOP ) return ProcessorAction.STOP
} }
@@ -49,7 +49,7 @@ abstract class FirTypeScope : FirScope() {
directOverriddenMap[functionSymbol] ?: return baseScope.processOverriddenFunctionsWithDepth(functionSymbol, processor) directOverriddenMap[functionSymbol] ?: return baseScope.processOverriddenFunctionsWithDepth(functionSymbol, processor)
for (overridden in directOverridden) { for (overridden in directOverridden) {
val overriddenDepth = if (overridden is FirNamedFunctionSymbol && overridden.isFakeOverride) 0 else 1 val overriddenDepth = if (overridden is FirNamedFunctionSymbol && overridden.overriddenSymbol != null) 0 else 1
if (!processor(overridden, overriddenDepth)) return ProcessorAction.STOP if (!processor(overridden, overriddenDepth)) return ProcessorAction.STOP
if (!baseScope.processOverriddenFunctionsWithDepth(overridden) { symbol, depth -> if (!baseScope.processOverriddenFunctionsWithDepth(overridden) { symbol, depth ->
processor(symbol, depth + overriddenDepth) processor(symbol, depth + overriddenDepth)
@@ -97,8 +97,8 @@ FILE fqName:<root> fileName:/implicitNotNullOnDelegatedImplementation.kt
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:K4 modality:FINAL visibility:public superTypes:[<root>.JUnrelatedFoo; <root>.IFoo]' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:K4 modality:FINAL visibility:public superTypes:[<root>.JUnrelatedFoo; <root>.IFoo]'
FUN name:foo visibility:public modality:FINAL <> ($this:<root>.K4) returnType:kotlin.String? FUN name:foo visibility:public modality:FINAL <> ($this:<root>.K4) returnType:kotlin.String?
overridden: overridden:
public abstract fun foo (): kotlin.String declared in <root>.IFoo
public open fun foo (): kotlin.String? declared in <root>.JUnrelatedFoo public open fun foo (): kotlin.String? declared in <root>.JUnrelatedFoo
public abstract fun foo (): kotlin.String declared in <root>.IFoo
$this: VALUE_PARAMETER name:<this> type:<root>.K4 $this: VALUE_PARAMETER name:<this> type:<root>.K4
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.String? declared in <root>.K4' RETURN type=kotlin.Nothing from='public final fun foo (): kotlin.String? declared in <root>.K4'