Introduce NewCallableReferenceResolvedCall and commonize other logic under NewAbstractResolvedCall

This commit is contained in:
Victor Petukhov
2021-09-20 15:51:18 +03:00
parent 65a8c9d89a
commit 3696bebb48
10 changed files with 362 additions and 65 deletions
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.util.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.*;
import org.jetbrains.kotlin.resolve.calls.tower.NewAbstractResolvedCall;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl;
import org.jetbrains.kotlin.resolve.calls.tower.NewVariableAsFunctionResolvedCallImpl;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
@@ -776,21 +777,21 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
}
private void recordSamValuesForNewInference(@NotNull ResolvedCall<?> call) {
NewResolvedCallImpl<?> newResolvedCall = getNewResolvedCallForCallWithPossibleSamConversions(call);
if (newResolvedCall == null) return;
NewAbstractResolvedCall<?> newResolvedCall = getNewResolvedCallForCallWithPossibleSamConversions(call);
if (!(newResolvedCall instanceof NewResolvedCallImpl<?>)) return;
Map<ValueParameterDescriptor, ResolvedValueArgument> arguments = newResolvedCall.getValueArguments();
for (ValueParameterDescriptor valueParameter : arguments.keySet()) {
ResolvedValueArgument argument = arguments.get(valueParameter);
if (argument instanceof ExpressionValueArgument) {
ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument();
if (valueArgument != null && newResolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) != null) {
if (valueArgument != null && ((NewResolvedCallImpl<?>)newResolvedCall).getExpectedTypeForSamConvertedArgument(valueArgument) != null) {
recordSamTypeOnArgumentExpression(valueParameter, valueArgument);
}
} else if (argument instanceof VarargValueArgument) {
VarargValueArgument varargValueArgument = (VarargValueArgument) argument;
for (ValueArgument valueArgument : varargValueArgument.getArguments()) {
if (valueArgument != null && newResolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) != null) {
if (valueArgument != null && ((NewResolvedCallImpl<?>)newResolvedCall).getExpectedTypeForSamConvertedArgument(valueArgument) != null) {
recordSamTypeOnArgumentExpression(valueParameter, valueArgument);
}
}
@@ -799,7 +800,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
}
@Nullable
private static NewResolvedCallImpl<?> getNewResolvedCallForCallWithPossibleSamConversions(@NotNull ResolvedCall<?> call) {
private static NewAbstractResolvedCall<?> getNewResolvedCallForCallWithPossibleSamConversions(@NotNull ResolvedCall<?> call) {
if (call instanceof NewVariableAsFunctionResolvedCallImpl) {
return ((NewVariableAsFunctionResolvedCallImpl) call).getFunctionCall();
}
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.resolve.calls.context.CallPosition
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.isCaptured
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
@@ -447,11 +447,11 @@ class BuilderInferenceSession(
return commonSystem.notFixedTypeVariables.all { it.value.constraints.isEmpty() }
}
private fun reportErrors(completedCall: CallInfo, resolvedCall: ResolvedCall<*>, errors: List<ConstraintSystemError>) {
private fun reportErrors(completedCall: CallInfo, resolvedCall: NewAbstractResolvedCall<*>, errors: List<ConstraintSystemError>) {
kotlinToResolvedCallTransformer.reportCallDiagnostic(
completedCall.context,
trace,
completedCall.callResolutionResult.resultCallAtom,
resolvedCall,
resolvedCall.resultingDescriptor,
errors.asDiagnostics()
)
@@ -528,7 +528,7 @@ class BuilderInferenceSession(
private fun completeCall(
callInfo: CallInfo,
atomCompleter: ResolvedAtomCompleter
): ResolvedCall<*>? {
): NewAbstractResolvedCall<*>? {
val resultCallAtom = callInfo.callResolutionResult.resultCallAtom
resultCallAtom.subResolvedAtoms?.forEach { subResolvedAtom ->
atomCompleter.completeAll(subResolvedAtom)
@@ -24,9 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.tower.KotlinToResolvedCallTransformerKt;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl;
import org.jetbrains.kotlin.resolve.calls.tower.NewVariableAsFunctionResolvedCallImpl;
import org.jetbrains.kotlin.resolve.calls.tower.*;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.resolve.calls.util.ResolvedCallUtilKt;
@@ -58,12 +56,12 @@ public class OverloadResolutionResultsUtil {
) {
if (results.isSingleResult() && context.contextDependency == ContextDependency.INDEPENDENT) {
ResolvedCall<D> resultingCall = results.getResultingCall();
NewResolvedCallImpl<?> newResolvedCall;
NewAbstractResolvedCall<?> newResolvedCall;
if (resultingCall instanceof NewVariableAsFunctionResolvedCallImpl) {
newResolvedCall = ((NewVariableAsFunctionResolvedCallImpl) resultingCall).getFunctionCall();
}
else if (resultingCall instanceof NewResolvedCallImpl) {
newResolvedCall = (NewResolvedCallImpl<?>) resultingCall;
else if (resultingCall instanceof NewAbstractResolvedCall<?>) {
newResolvedCall = (NewAbstractResolvedCall<?>) resultingCall;
} else {
newResolvedCall = null;
}
@@ -101,13 +101,13 @@ class KotlinToResolvedCallTransformer(
fun <D : CallableDescriptor> onlyTransform(
resolvedCallAtom: ResolvedCallAtom,
diagnostics: Collection<KotlinCallDiagnostic>,
): ResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null, null, diagnostics)
): NewAbstractResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null, null, diagnostics)
fun <D : CallableDescriptor> transformAndReport(
baseResolvedCall: CallResolutionResult,
context: BasicCallResolutionContext,
tracingStrategy: TracingStrategy,
): ResolvedCall<D> {
): NewAbstractResolvedCall<D> {
return when (baseResolvedCall) {
is PartialCallResolutionResult -> {
val candidate = baseResolvedCall.resultCallAtom
@@ -123,7 +123,7 @@ class KotlinToResolvedCallTransformer(
)
}
createStubResolvedCallAndWriteItToTrace(candidate, context.trace, baseResolvedCall.diagnostics, substitutor = null)
createStubResolvedCallAndWriteItToTrace<D>(candidate, context.trace, baseResolvedCall.diagnostics, substitutor = null)
}
is CompletedCallResolutionResult, is ErrorCallResolutionResult -> {
@@ -141,7 +141,7 @@ class KotlinToResolvedCallTransformer(
forwardCallToInferenceSession(baseResolvedCall, context, stub, tracingStrategy)
@Suppress("UNCHECKED_CAST")
return stub as ResolvedCall<D>
return stub as NewAbstractResolvedCall<D>
}
val ktPrimitiveCompleter = ResolvedAtomCompleter(
@@ -159,7 +159,7 @@ class KotlinToResolvedCallTransformer(
@Suppress("UNCHECKED_CAST")
val resolvedCall = ktPrimitiveCompleter.completeResolvedCall(
candidate, baseResolvedCall.completedDiagnostic(resultSubstitutor),
) as ResolvedCall<D>
) as NewAbstractResolvedCall<D>
forwardCallToInferenceSession(baseResolvedCall, context, resolvedCall, tracingStrategy)
@@ -174,7 +174,7 @@ class KotlinToResolvedCallTransformer(
private fun forwardCallToInferenceSession(
baseResolvedCall: CallResolutionResult,
context: BasicCallResolutionContext,
resolvedCall: ResolvedCall<*>,
resolvedCall: NewAbstractResolvedCall<*>,
tracingStrategy: TracingStrategy,
) {
if (baseResolvedCall is CompletedCallResolutionResult) {
@@ -187,7 +187,7 @@ class KotlinToResolvedCallTransformer(
trace: BindingTrace,
diagnostics: Collection<KotlinCallDiagnostic>,
substitutor: NewTypeSubstitutor?,
): ResolvedCall<D> {
): NewAbstractResolvedCall<D> {
val result = transformToResolvedCall<D>(candidate, trace, substitutor, diagnostics)
val psiKotlinCall = candidate.atom.psiKotlinCall
val tracing = psiKotlinCall.safeAs<PSIKotlinCallForInvoke>()?.baseCall?.tracingStrategy ?: psiKotlinCall.tracingStrategy
@@ -202,7 +202,7 @@ class KotlinToResolvedCallTransformer(
trace: BindingTrace?,
resultSubstitutor: NewTypeSubstitutor? = null, // if substitutor is not null, it means that this call is completed
diagnostics: Collection<KotlinCallDiagnostic>,
): ResolvedCall<D> {
): NewAbstractResolvedCall<D> {
val psiKotlinCall = completedCallAtom.atom.psiKotlinCall
return if (psiKotlinCall is PSIKotlinCallForInvoke) {
val diagnosticsForVariableCall = if (completedCallAtom.candidateDescriptor is FunctionDescriptor) emptyList() else diagnostics
@@ -211,7 +211,7 @@ class KotlinToResolvedCallTransformer(
NewVariableAsFunctionResolvedCallImpl(
createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnosticsForVariableCall),
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnosticsForFunctionCall),
) as ResolvedCall<D>
) as NewAbstractResolvedCall<D>
} else {
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
}
@@ -222,7 +222,7 @@ class KotlinToResolvedCallTransformer(
trace: BindingTrace?,
resultSubstitutor: NewTypeSubstitutor?,
diagnostics: Collection<KotlinCallDiagnostic>,
): NewResolvedCallImpl<D> {
): NewAbstractResolvedCall<D> {
if (trace != null) {
val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.getResolvedPsiKotlinCall<D>(trace)
if (storedResolvedCall != null) {
@@ -231,13 +231,16 @@ class KotlinToResolvedCallTransformer(
return storedResolvedCall
}
}
return NewResolvedCallImpl(
completedSimpleAtom,
resultSubstitutor,
diagnostics,
typeApproximator,
expressionTypingServices.languageVersionSettings
)
return if (completedSimpleAtom.atom.callKind == KotlinCallKind.CALLABLE_REFERENCE) {
NewCallableReferenceResolvedCall(
completedSimpleAtom as ResolvedCallableReferenceCallAtom, typeApproximator, resultSubstitutor
)
} else {
NewResolvedCallImpl(
completedSimpleAtom, resultSubstitutor, diagnostics, typeApproximator, expressionTypingServices.languageVersionSettings
)
}
}
fun runCallCheckers(resolvedCall: ResolvedCall<*>, callCheckerContext: CallCheckerContext) {
@@ -289,7 +292,9 @@ class KotlinToResolvedCallTransformer(
}
// todo very beginning code
fun runArgumentsChecks(context: BasicCallResolutionContext, resolvedCall: NewResolvedCallImpl<*>) {
fun runArgumentsChecks(context: BasicCallResolutionContext, resolvedCall: NewAbstractResolvedCall<*>) {
if (resolvedCall !is NewResolvedCallImpl<*>) return
for (valueArgument in resolvedCall.call.valueArguments) {
val argumentMapping = resolvedCall.getArgumentMapping(valueArgument!!)
val parameter: ValueParameterDescriptor?
@@ -404,7 +409,7 @@ class KotlinToResolvedCallTransformer(
if (!ExpressionTypingUtils.dependsOnExpectedType(expression))
null
else
expression.getResolvedCall(context.trace.bindingContext)
expression.getResolvedCall(context.trace.bindingContext) as? NewAbstractResolvedCall<*>
// See CallCompleter#updateRecordedTypeForArgument
private fun updateRecordedTypeForArgument(
@@ -461,32 +466,35 @@ class KotlinToResolvedCallTransformer(
}
internal fun bind(trace: BindingTrace, resolvedCall: ResolvedCall<*>) {
resolvedCall.safeAs<NewResolvedCallImpl<*>>()?.let { bind(trace, it) }
resolvedCall.safeAs<NewAbstractResolvedCall<*>>()?.let { bind(trace, it) }
resolvedCall.safeAs<NewVariableAsFunctionResolvedCallImpl>()?.let { bind(trace, it) }
}
fun reportDiagnostics(
context: BasicCallResolutionContext,
trace: BindingTrace,
resolvedCall: ResolvedCall<*>,
resolvedCall: NewAbstractResolvedCall<*>,
diagnostics: Collection<KotlinCallDiagnostic>,
) {
when (resolvedCall) {
is NewResolvedCallImpl ->
reportCallDiagnostic(context, trace, resolvedCall.resolvedCallAtom, resolvedCall.resultingDescriptor, diagnostics)
is NewVariableAsFunctionResolvedCallImpl -> {
val variableCall = resolvedCall.variableCall
val functionCall = resolvedCall.functionCall
reportCallDiagnostic(context, trace, variableCall.resolvedCallAtom, variableCall.resultingDescriptor, diagnostics)
reportCallDiagnostic(context, trace, functionCall.resolvedCallAtom, functionCall.resultingDescriptor, emptyList())
reportCallDiagnostic(context, trace, variableCall, variableCall.resultingDescriptor, diagnostics)
reportCallDiagnostic(context, trace, functionCall, functionCall.resultingDescriptor, emptyList())
}
else -> {
val resolvedCallAtom = resolvedCall.resolvedCallAtom
if (resolvedCallAtom != null) {
reportCallDiagnostic(context, trace, resolvedCall, resolvedCall.resultingDescriptor, diagnostics)
}
}
}
}
private fun bind(trace: BindingTrace, simpleResolvedCall: NewResolvedCallImpl<*>) {
val tracing = simpleResolvedCall.resolvedCallAtom.atom.psiKotlinCall.tracingStrategy
private fun bind(trace: BindingTrace, simpleResolvedCall: NewAbstractResolvedCall<*>) {
val tracing = simpleResolvedCall.psiKotlinCall.tracingStrategy
tracing.bindReference(trace, simpleResolvedCall)
tracing.bindResolvedCall(trace, simpleResolvedCall)
@@ -505,7 +513,7 @@ class KotlinToResolvedCallTransformer(
fun reportCallDiagnostic(
context: BasicCallResolutionContext,
trace: BindingTrace,
completedCallAtom: ResolvedCallAtom,
resolvedCall: NewAbstractResolvedCall<*>,
resultingDescriptor: CallableDescriptor,
diagnostics: Collection<KotlinCallDiagnostic>,
) {
@@ -513,14 +521,18 @@ class KotlinToResolvedCallTransformer(
val newContext = context.replaceBindingTrace(trackingTrace)
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
additionalDiagnosticReporter.reportAdditionalDiagnostics(completedCallAtom, resultingDescriptor, diagnosticHolder, diagnostics)
val resolvedCallAtom = resolvedCall.resolvedCallAtom
if (resolvedCallAtom != null) {
additionalDiagnosticReporter.reportAdditionalDiagnostics(resolvedCallAtom, resultingDescriptor, diagnosticHolder, diagnostics)
}
val allDiagnostics = diagnostics + diagnosticHolder.getDiagnostics()
val diagnosticReporter = DiagnosticReporterByTrackingStrategy(
constantExpressionEvaluator,
newContext,
completedCallAtom.atom.psiKotlinCall,
resolvedCall.psiKotlinCall,
context.dataFlowValueFactory,
allDiagnostics,
smartCastManager,
@@ -533,8 +545,7 @@ class KotlinToResolvedCallTransformer(
if (diagnostic is ResolvedUsingDeprecatedVisibility) {
reportResolvedUsingDeprecatedVisibility(
completedCallAtom.atom.psiKotlinCall.psiCall, completedCallAtom.candidateDescriptor,
resultingDescriptor, diagnostic, trace,
resolvedCall.psiKotlinCall.psiCall, resolvedCall.candidateDescriptor, resultingDescriptor, diagnostic, trace,
)
}
@@ -202,7 +202,7 @@ class PSIPartialCallInfo(
class PSICompletedCallInfo(
override val callResolutionResult: CompletedCallResolutionResult,
context: BasicCallResolutionContext,
val resolvedCall: ResolvedCall<*>,
val resolvedCall: NewAbstractResolvedCall<*>,
tracingStrategy: TracingStrategy
) : CallInfo(callResolutionResult, context, tracingStrategy), CompletedCallInfo
@@ -18,10 +18,13 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible
sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D> {
sealed class NewAbstractResolvedCall<D : CallableDescriptor> : ResolvedCall<D> {
abstract val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
abstract val kotlinCall: KotlinCall
protected abstract val languageVersionSettings: LanguageVersionSettings
abstract val languageVersionSettings: LanguageVersionSettings
abstract val resolvedCallAtom: ResolvedCallAtom?
abstract val psiKotlinCall: PSIKotlinCall
abstract val isCompleted: Boolean
protected var argumentToParameterMap: Map<ValueArgument, ArgumentMatchImpl>? = null
protected var _valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>? = null
@@ -39,9 +42,15 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D>
return _valueArguments!!
}
fun setValueArguments(m: Map<ValueParameterDescriptor, ResolvedValueArgument>) {
_valueArguments = m
}
open fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {}
override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? {
val arguments = ArrayList<ResolvedValueArgument?>(candidateDescriptor.valueParameters.size)
for (i in 0..candidateDescriptor.valueParameters.size - 1) {
for (i in 0 until candidateDescriptor.valueParameters.size) {
arguments.add(null)
}
@@ -86,7 +95,7 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D>
nonTrivialUpdatedResultInfo = dataFlowInfo.and(kotlinCall.psiKotlinCall.resultDataFlowInfo)
}
protected abstract fun argumentToParameterMap(
abstract fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
): Map<ValueArgument, ArgumentMatchImpl>
@@ -130,5 +139,4 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D>
}
}
}.compactIfPossible()
}
@@ -0,0 +1,257 @@
/*
* 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.resolve.calls.tower
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.inference.substitute
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateTypes
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.util.isNotSimpleCall
import org.jetbrains.kotlin.resolve.calls.util.toResolutionStatus
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
class NewCallableReferenceResolvedCall<D : CallableDescriptor>(
val resolvedAtom: ResolvedCallableReferenceAtom,
val typeApproximator: TypeApproximator,
substitutor: NewTypeSubstitutor?,
) : NewAbstractResolvedCall<D>() {
override var isCompleted = false
private set
override val resolvedCallAtom: MutableResolvedCallAtom? = when (resolvedAtom) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.resolvedCall
}
override val psiKotlinCall: PSIKotlinCall = when (resolvedAtom) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom.atom.psiKotlinCall
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.atom.call.psiKotlinCall
}
init {
setResultingSubstitutor(substitutor)
}
var diagnostics: Collection<KotlinCallDiagnostic> = mutableListOf()
private lateinit var resultingDescriptor: D
override fun getStatus(): ResolutionStatus {
return getResultApplicability(diagnostics).toResolutionStatus()
}
override fun getCandidateDescriptor(): D = when (resolvedAtom) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom.candidateDescriptor as D
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.candidate as D
}
override fun getResultingDescriptor(): D = resultingDescriptor
private var extensionReceiver = when (resolvedAtom) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom.extensionReceiverArgument?.receiverValue
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.extensionReceiver?.receiver?.receiverValue
}
private var dispatchReceiver = when (resolvedAtom) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom.dispatchReceiverArgument?.receiverValue
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.dispatchReceiver?.receiver?.receiverValue
}
override fun getExtensionReceiver(): ReceiverValue? = extensionReceiver
override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver
override fun getExplicitReceiverKind(): ExplicitReceiverKind = when (resolvedAtom) {
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.explicitReceiverKind
is ResolvedCallableReferenceCallAtom -> resolvedAtom.explicitReceiverKind
}
override fun getValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> = _valueArguments ?: emptyMap()
override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? {
val arguments = ArrayList<ResolvedValueArgument?>(candidateDescriptor.valueParameters.size)
for (i in 0 until candidateDescriptor.valueParameters.size) {
arguments.add(null)
}
for ((parameterDescriptor, value) in valueArguments) {
val oldValue = arguments.set(parameterDescriptor.index, value)
if (oldValue != null) {
return null
}
}
if (arguments.any { it == null }) return null
@Suppress("UNCHECKED_CAST")
return arguments as List<ResolvedValueArgument>
}
override fun getArgumentMapping(valueArgument: ValueArgument): ArgumentMapping = ArgumentUnmapped
override fun getTypeArguments(): Map<TypeParameterDescriptor, KotlinType> {
val typeParameters = candidateDescriptor.typeParameters.takeIf { it.isNotEmpty() } ?: return emptyMap()
return typeParameters.zip(typeArguments).toMap()
}
private lateinit var typeArguments: List<UnwrappedType>
override fun getDataFlowInfoForArguments(): DataFlowInfoForArguments =
MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
override fun getSmartCastDispatchReceiverType(): KotlinType? = null
private fun updateDispatchReceiverType(newType: KotlinType) {
if (dispatchReceiver?.type == newType) return
dispatchReceiver = dispatchReceiver?.replaceType(newType)
}
private fun updateExtensionReceiverType(newType: KotlinType) {
if (extensionReceiver?.type == newType) return
extensionReceiver = extensionReceiver?.replaceType(newType)
}
override fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
//clear cached values
if (substitutor != null) {
isCompleted = true
dispatchReceiver?.type?.let {
val newType = substitutor.safeSubstitute(it.unwrap())
updateDispatchReceiverType(newType)
}
extensionReceiver?.type?.let {
val newType = substitutor.safeSubstitute(it.unwrap())
updateExtensionReceiverType(newType)
}
}
@Suppress("UNCHECKED_CAST")
resultingDescriptor = substitutedResultingDescriptor(substitutor) as D
val sub = when (resolvedAtom) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom.freshVariablesSubstitutor
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.freshVariablesSubstitutor!!
}
typeArguments = sub.freshVariables.map {
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
typeApproximator
.approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation)
?: substituted
}
}
private fun getSubstitutorWithoutFlexibleTypes(
currentSubstitutor: NewTypeSubstitutor?,
explicitTypeArguments: List<SimpleTypeArgument>,
): NewTypeSubstitutor? {
if (currentSubstitutor !is NewTypeSubstitutorByConstructorMap || explicitTypeArguments.isEmpty()) return currentSubstitutor
if (!currentSubstitutor.map.any { (_, value) -> value.isFlexible() }) return currentSubstitutor
val sub = when (resolvedAtom) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom.freshVariablesSubstitutor
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.freshVariablesSubstitutor!!
}
val typeVariables = sub.freshVariables
val newSubstitutorMap = currentSubstitutor.map.toMutableMap()
explicitTypeArguments.forEachIndexed { index, typeArgument ->
val typeVariableConstructor = typeVariables.getOrNull(index)?.freshTypeConstructor ?: return@forEachIndexed
newSubstitutorMap[typeVariableConstructor] =
newSubstitutorMap[typeVariableConstructor]?.withNullabilityFromExplicitTypeArgument(typeArgument)
?: return@forEachIndexed
}
return NewTypeSubstitutorByConstructorMap(newSubstitutorMap)
}
private fun KotlinType.withNullabilityFromExplicitTypeArgument(typeArgument: SimpleTypeArgument) =
(if (typeArgument.type.isMarkedNullable) makeNullable() else makeNotNullable()).unwrap()
private fun substitutedResultingDescriptor(substitutor: NewTypeSubstitutor?): CallableDescriptor {
val candidateDescriptor = when (resolvedAtom) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom.candidateDescriptor
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.candidate
}
return when (candidateDescriptor) {
is ClassConstructorDescriptor, is SyntheticMemberDescriptor<*> -> {
val explicitTypeArguments = emptyList<SimpleTypeArgument>()
candidateDescriptor.substituteInferredVariablesAndApproximate(
getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments),
)
}
is FunctionDescriptor -> {
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor, candidateDescriptor.isNotSimpleCall())
}
is PropertyDescriptor -> {
if (candidateDescriptor.isNotSimpleCall()) {
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
} else {
candidateDescriptor
}
}
else -> candidateDescriptor
}
}
private fun CallableDescriptor.substituteInferredVariablesAndApproximate(
substitutor: NewTypeSubstitutor?,
shouldApproximate: Boolean = true
): CallableDescriptor {
val sub = when (resolvedAtom) {
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.freshVariablesSubstitutor!!
is ResolvedCallableReferenceCallAtom -> resolvedAtom.freshVariablesSubstitutor
}
val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
return substitute(sub).substituteAndApproximateTypes(
inferredTypeVariablesSubstitutor,
typeApproximator = if (shouldApproximate) typeApproximator else null,
positionDependentApproximation = true
)
}
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
get() = TODO("Not yet implemented")
override val kotlinCall: KotlinCall
get() = when (resolvedAtom) {
is ResolvedCallableReferenceArgumentAtom ->
(resolvedAtom.candidate?.kotlinCall as CallableReferenceKotlinCallArgument).call
is ResolvedCallableReferenceCallAtom -> resolvedAtom.atom
}
override val languageVersionSettings: LanguageVersionSettings
get() = TODO("Not yet implemented")
override fun containsOnlyOnlyInputTypesErrors(): Boolean {
TODO("Not yet implemented")
}
override fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
): Map<ValueArgument, ArgumentMatchImpl> {
TODO("Not yet implemented")
}
}
@@ -30,15 +30,16 @@ import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class NewResolvedCallImpl<D : CallableDescriptor>(
val resolvedCallAtom: ResolvedCallAtom,
override val resolvedCallAtom: ResolvedCallAtom,
substitutor: NewTypeSubstitutor?,
private var diagnostics: Collection<KotlinCallDiagnostic>,
private val typeApproximator: TypeApproximator,
override val languageVersionSettings: LanguageVersionSettings,
) : NewAbstractResolvedCall<D>() {
var isCompleted = false
override val psiKotlinCall: PSIKotlinCall = resolvedCallAtom.atom.psiKotlinCall
override var isCompleted = false
private set
private lateinit var resultingDescriptor: D
@@ -104,7 +105,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
dispatchReceiver = dispatchReceiver?.replaceType(newType)
}
fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
override fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
//clear cached values
argumentToParameterMap = null
_valueArguments = null
@@ -192,8 +193,12 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
// TODO: merge last two substitutors to avoid redundant descriptor substitutions
return substitute(resolvedCallAtom.freshVariablesSubstitutor).substitute(resolvedCallAtom.knownParametersSubstitutor)
.substituteAndApproximateTypes(inferredTypeVariablesSubstitutor, if (shouldApproximate) typeApproximator else null)
return substitute(resolvedCallAtom.freshVariablesSubstitutor)
.substitute(resolvedCallAtom.knownParametersSubstitutor)
.substituteAndApproximateTypes(
inferredTypeVariablesSubstitutor,
typeApproximator.takeIf { shouldApproximate }
)
}
fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? {
@@ -9,14 +9,32 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.utils.addToStdlib.cast
class NewVariableAsFunctionResolvedCallImpl(
override val variableCall: NewResolvedCallImpl<VariableDescriptor>,
override val functionCall: NewResolvedCallImpl<FunctionDescriptor>,
) : VariableAsFunctionResolvedCall, ResolvedCall<FunctionDescriptor> by functionCall {
val baseCall get() = functionCall.resolvedCallAtom.atom.psiKotlinCall.cast<PSIKotlinCallForInvoke>().baseCall
override val variableCall: NewAbstractResolvedCall<VariableDescriptor>,
override val functionCall: NewAbstractResolvedCall<FunctionDescriptor>,
) : VariableAsFunctionResolvedCall, NewAbstractResolvedCall<FunctionDescriptor>() {
override val resolvedCallAtom = functionCall.resolvedCallAtom
override val psiKotlinCall: PSIKotlinCall = functionCall.psiKotlinCall
val baseCall get() = functionCall.psiKotlinCall.cast<PSIKotlinCallForInvoke>().baseCall
override fun getStatus() = functionCall.status
override fun getCandidateDescriptor() = functionCall.candidateDescriptor
override fun getResultingDescriptor() = functionCall.resultingDescriptor
override fun getExtensionReceiver() = functionCall.extensionReceiver
override fun getDispatchReceiver() = functionCall.dispatchReceiver
override fun getExplicitReceiverKind() = functionCall.explicitReceiverKind
override fun getTypeArguments() = functionCall.typeArguments
override fun getSmartCastDispatchReceiverType() = functionCall.smartCastDispatchReceiverType
override val argumentMappingByOriginal = functionCall.argumentMappingByOriginal
override val kotlinCall = functionCall.kotlinCall
override val languageVersionSettings = functionCall.languageVersionSettings
override fun containsOnlyOnlyInputTypesErrors() = functionCall.containsOnlyOnlyInputTypesErrors()
override fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
) = functionCall.argumentToParameterMap(resultingDescriptor, valueArguments)
override val isCompleted: Boolean = functionCall.isCompleted
}