FIR: Rework default parameters propagation through overrides

This commit is contained in:
Denis Zharkov
2020-09-04 15:35:43 +03:00
parent ac666187b0
commit d67a1f9123
14 changed files with 95 additions and 57 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
fun FirSession.registerCommonComponents() {
register(FirDeclaredMemberScopeProvider::class, FirDeclaredMemberScopeProvider())
register(FirCorrespondingSupertypesCache::class, FirCorrespondingSupertypesCache(this))
register(FirDefaultParametersResolver::class, FirDefaultParametersResolver())
register(FirExtensionService::class, FirExtensionService(this))
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.create(this))
@@ -394,7 +394,8 @@ class FirCallResolver(
if (constructorSymbol == null) return null
val candidate = CandidateFactory(transformer.resolutionContext, callInfo).createCandidate(
constructorSymbol!!,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
scope = null
)
val applicability = components.resolutionStageRunner.processCandidate(candidate, transformer.resolutionContext)
return ResolutionResult(callInfo, applicability, listOf(candidate))
@@ -0,0 +1,41 @@
/*
* 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.resolve
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
class FirDefaultParametersResolver : FirSessionComponent {
fun declaresDefaultValue(
valueParameter: FirValueParameter,
function: FirFunction<*>,
originScope: FirScope?,
index: Int,
): Boolean {
if (valueParameter.defaultValue != null) return true
if (originScope !is FirTypeScope) return false
var result = false
originScope.processOverriddenFunctions(function.symbol) { overridden ->
if (overridden.fir.valueParameters[index].defaultValue != null) {
result = true
return@processOverriddenFunctions ProcessorAction.STOP
}
ProcessorAction.NEXT
}
return result
}
}
internal val FirSession.defaultParameterResolver: FirDefaultParametersResolver by FirSession.sessionComponentAccessor()
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.builder.buildNamedArgumentExpression
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedCallableReferenceTarget
@@ -106,7 +107,8 @@ private fun buildReflectionType(
is FirFunction -> {
val unboundReferenceTarget = if (receiverType != null) 1 else 0
val callableReferenceAdaptation =
getCallableReferenceAdaptation(context.session, fir, callInfo.expectedType, unboundReferenceTarget)
context.bodyResolveComponents
.getCallableReferenceAdaptation(context.session, fir, callInfo.expectedType, unboundReferenceTarget)
val parameters = mutableListOf<ConeKotlinType>()
@@ -153,7 +155,7 @@ private fun CallableReferenceAdaptation?.needCompatibilityResolveForCallableRefe
mappedArguments.values.any { it is ResolvedCallArgument.VarargArgument }
}
private fun getCallableReferenceAdaptation(
private fun BodyResolveComponents.getCallableReferenceAdaptation(
session: FirSession,
function: FirFunction<*>,
expectedType: ConeKotlinType?,
@@ -169,7 +171,8 @@ private fun getCallableReferenceAdaptation(
if (expectedArgumentsCount < 0) return null
val fakeArguments = createFakeArgumentsForReference(function, expectedArgumentsCount, inputTypes, unboundReceiverCount)
val argumentMapping = mapArguments(fakeArguments, function)
// TODO: Use correct originScope
val argumentMapping = mapArguments(fakeArguments, function, originScope = null)
if (argumentMapping.diagnostics.any { !it.applicability.isSuccess }) return null
/**
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
import org.jetbrains.kotlin.fir.resolve.inference.PostponedResolvedAtom
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
@@ -82,7 +83,8 @@ class Candidate(
val explicitReceiverKind: ExplicitReceiverKind,
val constraintSystemFactory: InferenceComponents.ConstraintSystemFactory,
private val baseSystem: ConstraintStorage,
val callInfo: CallInfo
val callInfo: CallInfo,
val originScope: FirScope?,
) {
var systemInitialized: Boolean = false
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildErrorProperty
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirErrorFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirErrorPropertySymbol
@@ -49,6 +50,7 @@ class CandidateFactory private constructor(
fun createCandidate(
symbol: AbstractFirBasedSymbol<*>,
explicitReceiverKind: ExplicitReceiverKind,
scope: FirScope?,
dispatchReceiverValue: ReceiverValue? = null,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>? = null,
builtInExtensionFunctionReceiverValue: ReceiverValue? = null
@@ -58,7 +60,8 @@ class CandidateFactory private constructor(
explicitReceiverKind, context.inferenceComponents.constraintSystemFactory, baseSystem,
builtInExtensionFunctionReceiverValue?.receiverExpression?.let {
callInfo.withReceiverAsArgument(it)
} ?: callInfo
} ?: callInfo,
scope,
)
}
@@ -79,7 +82,8 @@ class CandidateFactory private constructor(
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
context.inferenceComponents.constraintSystemFactory,
baseSystem,
callInfo
callInfo,
originScope = null,
)
}
@@ -14,6 +14,9 @@ import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirSpreadArgumentExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildNamedArgumentExpression
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.defaultParameterResolver
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.name.Name
import java.util.*
import kotlin.collections.ArrayList
@@ -45,9 +48,10 @@ data class ArgumentMapping(
private val EmptyArgumentMapping = ArgumentMapping(emptyMap(), emptyList())
fun mapArguments(
fun BodyResolveComponents.mapArguments(
arguments: List<FirExpression>,
function: FirFunction<*>
function: FirFunction<*>,
originScope: FirScope?,
): ArgumentMapping {
if (arguments.isEmpty() && function.valueParameters.isEmpty()) {
return EmptyArgumentMapping
@@ -77,7 +81,7 @@ fun mapArguments(
}
}
val processor = FirCallArgumentsProcessor(function)
val processor = FirCallArgumentsProcessor(function, this, originScope)
processor.processArgumentsInParenthesis(argumentsInParenthesis)
if (externalArgument != null) {
processor.processExternalArgument(externalArgument)
@@ -87,7 +91,11 @@ fun mapArguments(
return ArgumentMapping(processor.result, processor.diagnostics ?: emptyList())
}
private class FirCallArgumentsProcessor(private val function: FirFunction<*>) {
private class FirCallArgumentsProcessor(
private val function: FirFunction<*>,
private val bodyResolveComponents: BodyResolveComponents,
private val originScope: FirScope?,
) {
private var state = State.POSITION_ARGUMENTS
private var currentPositionedParameterIndex = 0
private var varargArguments: MutableList<FirExpression>? = null
@@ -207,9 +215,9 @@ private class FirCallArgumentsProcessor(private val function: FirFunction<*>) {
}
}
for (parameter in parameters) {
for ((index, parameter) in parameters.withIndex()) {
if (!result.containsKey(parameter)) {
if (parameter.defaultValue != null) {
if (bodyResolveComponents.session.defaultParameterResolver.declaresDefaultValue(parameter, function, originScope, index)) {
result[parameter] = ResolvedCallArgument.DefaultArgument
} else if (parameter.isVararg) {
result[parameter] = ResolvedCallArgument.VarargArgument(emptyList())
@@ -169,7 +169,7 @@ internal object MapArguments : ResolutionStage() {
val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportDiagnostic(HiddenCandidate)
val function = symbol.fir
val mapping = mapArguments(callInfo.arguments, function)
val mapping = context.bodyResolveComponents.mapArguments(callInfo.arguments, function, candidate.originScope)
candidate.argumentMapping = mapping.toArgumentToParameterMapping()
mapping.diagnostics.forEach(sink::reportDiagnostic)
@@ -105,6 +105,7 @@ class FirTowerResolver(
candidateFactory.createCandidate(
it,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
scope,
dispatchReceiver,
implicitExtensionReceiverValue = null,
builtInExtensionFunctionReceiverValue = null
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -147,6 +148,7 @@ private class TowerScopeLevelProcessor(
symbol: AbstractFirBasedSymbol<*>,
dispatchReceiverValue: ReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
scope: FirScope,
builtInExtensionFunctionReceiverValue: ReceiverValue?
) {
// Check explicit extension receiver for default package members
@@ -179,6 +181,7 @@ private class TowerScopeLevelProcessor(
group, candidateFactory.createCandidate(
symbol,
explicitReceiverKind,
scope,
dispatchReceiverValue,
implicitExtensionReceiverValue,
builtInExtensionFunctionReceiverValue
@@ -48,6 +48,7 @@ interface TowerScopeLevel {
symbol: T,
dispatchReceiverValue: ReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
scope: FirScope,
builtInExtensionFunctionReceiverValue: ReceiverValue? = null
)
}
@@ -94,18 +95,20 @@ class MemberScopeTowerLevel(
output.consumeCandidate(
candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>,
scope
)
if (implicitExtensionInvokeMode) {
output.consumeCandidate(
candidate, dispatchReceiverValue,
implicitExtensionReceiverValue = null,
scope,
builtInExtensionFunctionReceiverValue = this.extensionReceiver
)
}
} else if (candidate is FirClassLikeSymbol<*>) {
output.consumeCandidate(candidate, null, extensionReceiver as? ImplicitReceiverValue<*>)
output.consumeCandidate(candidate, null, extensionReceiver as? ImplicitReceiverValue<*>, scope)
}
}
@@ -113,7 +116,7 @@ class MemberScopeTowerLevel(
val withSynthetic = FirSyntheticPropertiesScope(session, scope)
withSynthetic.processScopeMembers { symbol ->
empty = false
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), null)
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), null, scope)
}
}
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
@@ -226,7 +229,8 @@ class ScopeTowerLevel(
@Suppress("UNCHECKED_CAST")
processor.consumeCandidate(
unwrappedCandidate as T, dispatchReceiverValue,
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>,
scope
)
}
}
@@ -256,7 +260,8 @@ class ScopeTowerLevel(
empty = false
processor.consumeCandidate(
it as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = null
implicitExtensionReceiverValue = null,
scope = scope
)
}
}
@@ -175,7 +175,8 @@ class FirSyntheticCallGenerator(
private fun generateCandidate(callInfo: CallInfo, function: FirSimpleFunction, context: ResolutionContext): Candidate =
CandidateFactory(context, callInfo).createCandidate(
symbol = function.symbol,
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
scope = null
)
private fun generateCallInfo(name: Name, argumentList: FirArgumentList, callKind: CallKind) = CallInfo(
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.*
@@ -36,11 +35,10 @@ abstract class AbstractFirUseSiteMemberScope(
name: Name
): Collection<FirFunctionSymbol<*>> = mutableListOf<FirFunctionSymbol<*>>().apply {
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
declaredMemberScope.processFunctionsByName(name) {
if (it.isStatic) return@processFunctionsByName
val directOverridden = computeDirectOverridden(it)
this@AbstractFirUseSiteMemberScope.directOverriddenFunctions[it] = directOverridden
val symbol = processInheritedDefaultParameters(it, directOverridden)
declaredMemberScope.processFunctionsByName(name) { symbol ->
if (symbol.isStatic) return@processFunctionsByName
val directOverridden = computeDirectOverridden(symbol)
this@AbstractFirUseSiteMemberScope.directOverriddenFunctions[symbol] = directOverridden
overrideCandidates += symbol
add(symbol)
}
@@ -70,37 +68,6 @@ abstract class AbstractFirUseSiteMemberScope(
return result
}
private fun processInheritedDefaultParameters(
symbol: FirFunctionSymbol<*>,
directOverridden: Collection<FirFunctionSymbol<*>>
): FirFunctionSymbol<*> {
val firSimpleFunction = symbol.fir as? FirSimpleFunction ?: return symbol
if (firSimpleFunction.valueParameters.isEmpty() || firSimpleFunction.valueParameters.any { it.defaultValue != null }) return symbol
val overriddenWithDefault: FirFunction<*> =
directOverridden.singleOrNull {
it.fir.valueParameters.any { parameter -> parameter.defaultValue != null }
}?.fir ?: return symbol
val newSymbol = FirNamedFunctionSymbol(symbol.callableId, false, null)
createFunctionCopy(firSimpleFunction, newSymbol).apply {
resolvePhase = firSimpleFunction.resolvePhase
typeParameters += firSimpleFunction.typeParameters
valueParameters += firSimpleFunction.valueParameters.zip(overriddenWithDefault.valueParameters)
.map { (overrideParameter, overriddenParameter) ->
if (overriddenParameter.defaultValue != null)
createValueParameterCopy(overrideParameter, overriddenParameter.defaultValue).apply {
annotations += overrideParameter.annotations
}.build()
else
overrideParameter
}
}.build()
return newSymbol
}
override fun processDirectOverriddenFunctionsWithBaseScope(
functionSymbol: FirFunctionSymbol<*>,
processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction
@@ -69,6 +69,7 @@ class SingleCandidateResolver(
explicitReceiverKind = explicitReceiverKind,
dispatchReceiverValue = dispatchReceiverValue,
implicitExtensionReceiverValue = implicitExtensionReceiverValue,
scope = null,
)
val applicability = resolutionStageRunner.processCandidate(candidate, resolutionContext, stopOnFirstError = true)