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.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.util.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.util.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.*; 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.NewResolvedCallImpl;
import org.jetbrains.kotlin.resolve.calls.tower.NewVariableAsFunctionResolvedCallImpl; import org.jetbrains.kotlin.resolve.calls.tower.NewVariableAsFunctionResolvedCallImpl;
import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.ConstantValue;
@@ -776,21 +777,21 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
} }
private void recordSamValuesForNewInference(@NotNull ResolvedCall<?> call) { private void recordSamValuesForNewInference(@NotNull ResolvedCall<?> call) {
NewResolvedCallImpl<?> newResolvedCall = getNewResolvedCallForCallWithPossibleSamConversions(call); NewAbstractResolvedCall<?> newResolvedCall = getNewResolvedCallForCallWithPossibleSamConversions(call);
if (newResolvedCall == null) return; if (!(newResolvedCall instanceof NewResolvedCallImpl<?>)) return;
Map<ValueParameterDescriptor, ResolvedValueArgument> arguments = newResolvedCall.getValueArguments(); Map<ValueParameterDescriptor, ResolvedValueArgument> arguments = newResolvedCall.getValueArguments();
for (ValueParameterDescriptor valueParameter : arguments.keySet()) { for (ValueParameterDescriptor valueParameter : arguments.keySet()) {
ResolvedValueArgument argument = arguments.get(valueParameter); ResolvedValueArgument argument = arguments.get(valueParameter);
if (argument instanceof ExpressionValueArgument) { if (argument instanceof ExpressionValueArgument) {
ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument(); ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument();
if (valueArgument != null && newResolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) != null) { if (valueArgument != null && ((NewResolvedCallImpl<?>)newResolvedCall).getExpectedTypeForSamConvertedArgument(valueArgument) != null) {
recordSamTypeOnArgumentExpression(valueParameter, valueArgument); recordSamTypeOnArgumentExpression(valueParameter, valueArgument);
} }
} else if (argument instanceof VarargValueArgument) { } else if (argument instanceof VarargValueArgument) {
VarargValueArgument varargValueArgument = (VarargValueArgument) argument; VarargValueArgument varargValueArgument = (VarargValueArgument) argument;
for (ValueArgument valueArgument : varargValueArgument.getArguments()) { for (ValueArgument valueArgument : varargValueArgument.getArguments()) {
if (valueArgument != null && newResolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) != null) { if (valueArgument != null && ((NewResolvedCallImpl<?>)newResolvedCall).getExpectedTypeForSamConvertedArgument(valueArgument) != null) {
recordSamTypeOnArgumentExpression(valueParameter, valueArgument); recordSamTypeOnArgumentExpression(valueParameter, valueArgument);
} }
} }
@@ -799,7 +800,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
} }
@Nullable @Nullable
private static NewResolvedCallImpl<?> getNewResolvedCallForCallWithPossibleSamConversions(@NotNull ResolvedCall<?> call) { private static NewAbstractResolvedCall<?> getNewResolvedCallForCallWithPossibleSamConversions(@NotNull ResolvedCall<?> call) {
if (call instanceof NewVariableAsFunctionResolvedCallImpl) { if (call instanceof NewVariableAsFunctionResolvedCallImpl) {
return ((NewVariableAsFunctionResolvedCallImpl) call).getFunctionCall(); 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.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.isCaptured import org.jetbrains.kotlin.resolve.calls.inference.isCaptured
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution 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.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructorSubstitution import org.jetbrains.kotlin.types.TypeConstructorSubstitution
@@ -447,11 +447,11 @@ class BuilderInferenceSession(
return commonSystem.notFixedTypeVariables.all { it.value.constraints.isEmpty() } 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( kotlinToResolvedCallTransformer.reportCallDiagnostic(
completedCall.context, completedCall.context,
trace, trace,
completedCall.callResolutionResult.resultCallAtom, resolvedCall,
resolvedCall.resultingDescriptor, resolvedCall.resultingDescriptor,
errors.asDiagnostics() errors.asDiagnostics()
) )
@@ -528,7 +528,7 @@ class BuilderInferenceSession(
private fun completeCall( private fun completeCall(
callInfo: CallInfo, callInfo: CallInfo,
atomCompleter: ResolvedAtomCompleter atomCompleter: ResolvedAtomCompleter
): ResolvedCall<*>? { ): NewAbstractResolvedCall<*>? {
val resultCallAtom = callInfo.callResolutionResult.resultCallAtom val resultCallAtom = callInfo.callResolutionResult.resultCallAtom
resultCallAtom.subResolvedAtoms?.forEach { subResolvedAtom -> resultCallAtom.subResolvedAtoms?.forEach { subResolvedAtom ->
atomCompleter.completeAll(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.context.ResolutionContext;
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.tower.KotlinToResolvedCallTransformerKt; import org.jetbrains.kotlin.resolve.calls.tower.*;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl;
import org.jetbrains.kotlin.resolve.calls.tower.NewVariableAsFunctionResolvedCallImpl;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.resolve.calls.util.ResolvedCallUtilKt; import org.jetbrains.kotlin.resolve.calls.util.ResolvedCallUtilKt;
@@ -58,12 +56,12 @@ public class OverloadResolutionResultsUtil {
) { ) {
if (results.isSingleResult() && context.contextDependency == ContextDependency.INDEPENDENT) { if (results.isSingleResult() && context.contextDependency == ContextDependency.INDEPENDENT) {
ResolvedCall<D> resultingCall = results.getResultingCall(); ResolvedCall<D> resultingCall = results.getResultingCall();
NewResolvedCallImpl<?> newResolvedCall; NewAbstractResolvedCall<?> newResolvedCall;
if (resultingCall instanceof NewVariableAsFunctionResolvedCallImpl) { if (resultingCall instanceof NewVariableAsFunctionResolvedCallImpl) {
newResolvedCall = ((NewVariableAsFunctionResolvedCallImpl) resultingCall).getFunctionCall(); newResolvedCall = ((NewVariableAsFunctionResolvedCallImpl) resultingCall).getFunctionCall();
} }
else if (resultingCall instanceof NewResolvedCallImpl) { else if (resultingCall instanceof NewAbstractResolvedCall<?>) {
newResolvedCall = (NewResolvedCallImpl<?>) resultingCall; newResolvedCall = (NewAbstractResolvedCall<?>) resultingCall;
} else { } else {
newResolvedCall = null; newResolvedCall = null;
} }
@@ -101,13 +101,13 @@ class KotlinToResolvedCallTransformer(
fun <D : CallableDescriptor> onlyTransform( fun <D : CallableDescriptor> onlyTransform(
resolvedCallAtom: ResolvedCallAtom, resolvedCallAtom: ResolvedCallAtom,
diagnostics: Collection<KotlinCallDiagnostic>, diagnostics: Collection<KotlinCallDiagnostic>,
): ResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null, null, diagnostics) ): NewAbstractResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null, null, diagnostics)
fun <D : CallableDescriptor> transformAndReport( fun <D : CallableDescriptor> transformAndReport(
baseResolvedCall: CallResolutionResult, baseResolvedCall: CallResolutionResult,
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
tracingStrategy: TracingStrategy, tracingStrategy: TracingStrategy,
): ResolvedCall<D> { ): NewAbstractResolvedCall<D> {
return when (baseResolvedCall) { return when (baseResolvedCall) {
is PartialCallResolutionResult -> { is PartialCallResolutionResult -> {
val candidate = baseResolvedCall.resultCallAtom 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 -> { is CompletedCallResolutionResult, is ErrorCallResolutionResult -> {
@@ -141,7 +141,7 @@ class KotlinToResolvedCallTransformer(
forwardCallToInferenceSession(baseResolvedCall, context, stub, tracingStrategy) forwardCallToInferenceSession(baseResolvedCall, context, stub, tracingStrategy)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return stub as ResolvedCall<D> return stub as NewAbstractResolvedCall<D>
} }
val ktPrimitiveCompleter = ResolvedAtomCompleter( val ktPrimitiveCompleter = ResolvedAtomCompleter(
@@ -159,7 +159,7 @@ class KotlinToResolvedCallTransformer(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val resolvedCall = ktPrimitiveCompleter.completeResolvedCall( val resolvedCall = ktPrimitiveCompleter.completeResolvedCall(
candidate, baseResolvedCall.completedDiagnostic(resultSubstitutor), candidate, baseResolvedCall.completedDiagnostic(resultSubstitutor),
) as ResolvedCall<D> ) as NewAbstractResolvedCall<D>
forwardCallToInferenceSession(baseResolvedCall, context, resolvedCall, tracingStrategy) forwardCallToInferenceSession(baseResolvedCall, context, resolvedCall, tracingStrategy)
@@ -174,7 +174,7 @@ class KotlinToResolvedCallTransformer(
private fun forwardCallToInferenceSession( private fun forwardCallToInferenceSession(
baseResolvedCall: CallResolutionResult, baseResolvedCall: CallResolutionResult,
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
resolvedCall: ResolvedCall<*>, resolvedCall: NewAbstractResolvedCall<*>,
tracingStrategy: TracingStrategy, tracingStrategy: TracingStrategy,
) { ) {
if (baseResolvedCall is CompletedCallResolutionResult) { if (baseResolvedCall is CompletedCallResolutionResult) {
@@ -187,7 +187,7 @@ class KotlinToResolvedCallTransformer(
trace: BindingTrace, trace: BindingTrace,
diagnostics: Collection<KotlinCallDiagnostic>, diagnostics: Collection<KotlinCallDiagnostic>,
substitutor: NewTypeSubstitutor?, substitutor: NewTypeSubstitutor?,
): ResolvedCall<D> { ): NewAbstractResolvedCall<D> {
val result = transformToResolvedCall<D>(candidate, trace, substitutor, diagnostics) val result = transformToResolvedCall<D>(candidate, trace, substitutor, diagnostics)
val psiKotlinCall = candidate.atom.psiKotlinCall val psiKotlinCall = candidate.atom.psiKotlinCall
val tracing = psiKotlinCall.safeAs<PSIKotlinCallForInvoke>()?.baseCall?.tracingStrategy ?: psiKotlinCall.tracingStrategy val tracing = psiKotlinCall.safeAs<PSIKotlinCallForInvoke>()?.baseCall?.tracingStrategy ?: psiKotlinCall.tracingStrategy
@@ -202,7 +202,7 @@ class KotlinToResolvedCallTransformer(
trace: BindingTrace?, trace: BindingTrace?,
resultSubstitutor: NewTypeSubstitutor? = null, // if substitutor is not null, it means that this call is completed resultSubstitutor: NewTypeSubstitutor? = null, // if substitutor is not null, it means that this call is completed
diagnostics: Collection<KotlinCallDiagnostic>, diagnostics: Collection<KotlinCallDiagnostic>,
): ResolvedCall<D> { ): NewAbstractResolvedCall<D> {
val psiKotlinCall = completedCallAtom.atom.psiKotlinCall val psiKotlinCall = completedCallAtom.atom.psiKotlinCall
return if (psiKotlinCall is PSIKotlinCallForInvoke) { return if (psiKotlinCall is PSIKotlinCallForInvoke) {
val diagnosticsForVariableCall = if (completedCallAtom.candidateDescriptor is FunctionDescriptor) emptyList() else diagnostics val diagnosticsForVariableCall = if (completedCallAtom.candidateDescriptor is FunctionDescriptor) emptyList() else diagnostics
@@ -211,7 +211,7 @@ class KotlinToResolvedCallTransformer(
NewVariableAsFunctionResolvedCallImpl( NewVariableAsFunctionResolvedCallImpl(
createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnosticsForVariableCall), createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnosticsForVariableCall),
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnosticsForFunctionCall), createOrGet(completedCallAtom, trace, resultSubstitutor, diagnosticsForFunctionCall),
) as ResolvedCall<D> ) as NewAbstractResolvedCall<D>
} else { } else {
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics) createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
} }
@@ -222,7 +222,7 @@ class KotlinToResolvedCallTransformer(
trace: BindingTrace?, trace: BindingTrace?,
resultSubstitutor: NewTypeSubstitutor?, resultSubstitutor: NewTypeSubstitutor?,
diagnostics: Collection<KotlinCallDiagnostic>, diagnostics: Collection<KotlinCallDiagnostic>,
): NewResolvedCallImpl<D> { ): NewAbstractResolvedCall<D> {
if (trace != null) { if (trace != null) {
val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.getResolvedPsiKotlinCall<D>(trace) val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.getResolvedPsiKotlinCall<D>(trace)
if (storedResolvedCall != null) { if (storedResolvedCall != null) {
@@ -231,13 +231,16 @@ class KotlinToResolvedCallTransformer(
return storedResolvedCall return storedResolvedCall
} }
} }
return NewResolvedCallImpl(
completedSimpleAtom, return if (completedSimpleAtom.atom.callKind == KotlinCallKind.CALLABLE_REFERENCE) {
resultSubstitutor, NewCallableReferenceResolvedCall(
diagnostics, completedSimpleAtom as ResolvedCallableReferenceCallAtom, typeApproximator, resultSubstitutor
typeApproximator, )
expressionTypingServices.languageVersionSettings } else {
) NewResolvedCallImpl(
completedSimpleAtom, resultSubstitutor, diagnostics, typeApproximator, expressionTypingServices.languageVersionSettings
)
}
} }
fun runCallCheckers(resolvedCall: ResolvedCall<*>, callCheckerContext: CallCheckerContext) { fun runCallCheckers(resolvedCall: ResolvedCall<*>, callCheckerContext: CallCheckerContext) {
@@ -289,7 +292,9 @@ class KotlinToResolvedCallTransformer(
} }
// todo very beginning code // 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) { for (valueArgument in resolvedCall.call.valueArguments) {
val argumentMapping = resolvedCall.getArgumentMapping(valueArgument!!) val argumentMapping = resolvedCall.getArgumentMapping(valueArgument!!)
val parameter: ValueParameterDescriptor? val parameter: ValueParameterDescriptor?
@@ -404,7 +409,7 @@ class KotlinToResolvedCallTransformer(
if (!ExpressionTypingUtils.dependsOnExpectedType(expression)) if (!ExpressionTypingUtils.dependsOnExpectedType(expression))
null null
else else
expression.getResolvedCall(context.trace.bindingContext) expression.getResolvedCall(context.trace.bindingContext) as? NewAbstractResolvedCall<*>
// See CallCompleter#updateRecordedTypeForArgument // See CallCompleter#updateRecordedTypeForArgument
private fun updateRecordedTypeForArgument( private fun updateRecordedTypeForArgument(
@@ -461,32 +466,35 @@ class KotlinToResolvedCallTransformer(
} }
internal fun bind(trace: BindingTrace, resolvedCall: ResolvedCall<*>) { 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) } resolvedCall.safeAs<NewVariableAsFunctionResolvedCallImpl>()?.let { bind(trace, it) }
} }
fun reportDiagnostics( fun reportDiagnostics(
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
trace: BindingTrace, trace: BindingTrace,
resolvedCall: ResolvedCall<*>, resolvedCall: NewAbstractResolvedCall<*>,
diagnostics: Collection<KotlinCallDiagnostic>, diagnostics: Collection<KotlinCallDiagnostic>,
) { ) {
when (resolvedCall) { when (resolvedCall) {
is NewResolvedCallImpl ->
reportCallDiagnostic(context, trace, resolvedCall.resolvedCallAtom, resolvedCall.resultingDescriptor, diagnostics)
is NewVariableAsFunctionResolvedCallImpl -> { is NewVariableAsFunctionResolvedCallImpl -> {
val variableCall = resolvedCall.variableCall val variableCall = resolvedCall.variableCall
val functionCall = resolvedCall.functionCall val functionCall = resolvedCall.functionCall
reportCallDiagnostic(context, trace, variableCall.resolvedCallAtom, variableCall.resultingDescriptor, diagnostics) reportCallDiagnostic(context, trace, variableCall, variableCall.resultingDescriptor, diagnostics)
reportCallDiagnostic(context, trace, functionCall.resolvedCallAtom, functionCall.resultingDescriptor, emptyList()) 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<*>) { private fun bind(trace: BindingTrace, simpleResolvedCall: NewAbstractResolvedCall<*>) {
val tracing = simpleResolvedCall.resolvedCallAtom.atom.psiKotlinCall.tracingStrategy val tracing = simpleResolvedCall.psiKotlinCall.tracingStrategy
tracing.bindReference(trace, simpleResolvedCall) tracing.bindReference(trace, simpleResolvedCall)
tracing.bindResolvedCall(trace, simpleResolvedCall) tracing.bindResolvedCall(trace, simpleResolvedCall)
@@ -505,7 +513,7 @@ class KotlinToResolvedCallTransformer(
fun reportCallDiagnostic( fun reportCallDiagnostic(
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
trace: BindingTrace, trace: BindingTrace,
completedCallAtom: ResolvedCallAtom, resolvedCall: NewAbstractResolvedCall<*>,
resultingDescriptor: CallableDescriptor, resultingDescriptor: CallableDescriptor,
diagnostics: Collection<KotlinCallDiagnostic>, diagnostics: Collection<KotlinCallDiagnostic>,
) { ) {
@@ -513,14 +521,18 @@ class KotlinToResolvedCallTransformer(
val newContext = context.replaceBindingTrace(trackingTrace) val newContext = context.replaceBindingTrace(trackingTrace)
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder() 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 allDiagnostics = diagnostics + diagnosticHolder.getDiagnostics()
val diagnosticReporter = DiagnosticReporterByTrackingStrategy( val diagnosticReporter = DiagnosticReporterByTrackingStrategy(
constantExpressionEvaluator, constantExpressionEvaluator,
newContext, newContext,
completedCallAtom.atom.psiKotlinCall, resolvedCall.psiKotlinCall,
context.dataFlowValueFactory, context.dataFlowValueFactory,
allDiagnostics, allDiagnostics,
smartCastManager, smartCastManager,
@@ -533,8 +545,7 @@ class KotlinToResolvedCallTransformer(
if (diagnostic is ResolvedUsingDeprecatedVisibility) { if (diagnostic is ResolvedUsingDeprecatedVisibility) {
reportResolvedUsingDeprecatedVisibility( reportResolvedUsingDeprecatedVisibility(
completedCallAtom.atom.psiKotlinCall.psiCall, completedCallAtom.candidateDescriptor, resolvedCall.psiKotlinCall.psiCall, resolvedCall.candidateDescriptor, resultingDescriptor, diagnostic, trace,
resultingDescriptor, diagnostic, trace,
) )
} }
@@ -202,7 +202,7 @@ class PSIPartialCallInfo(
class PSICompletedCallInfo( class PSICompletedCallInfo(
override val callResolutionResult: CompletedCallResolutionResult, override val callResolutionResult: CompletedCallResolutionResult,
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
val resolvedCall: ResolvedCall<*>, val resolvedCall: NewAbstractResolvedCall<*>,
tracingStrategy: TracingStrategy tracingStrategy: TracingStrategy
) : CallInfo(callResolutionResult, context, tracingStrategy), CompletedCallInfo ) : 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.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible 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 argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
abstract val kotlinCall: KotlinCall 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 argumentToParameterMap: Map<ValueArgument, ArgumentMatchImpl>? = null
protected var _valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>? = null protected var _valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>? = null
@@ -39,9 +42,15 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D>
return _valueArguments!! return _valueArguments!!
} }
fun setValueArguments(m: Map<ValueParameterDescriptor, ResolvedValueArgument>) {
_valueArguments = m
}
open fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {}
override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? { override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? {
val arguments = ArrayList<ResolvedValueArgument?>(candidateDescriptor.valueParameters.size) 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) arguments.add(null)
} }
@@ -86,7 +95,7 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D>
nonTrivialUpdatedResultInfo = dataFlowInfo.and(kotlinCall.psiKotlinCall.resultDataFlowInfo) nonTrivialUpdatedResultInfo = dataFlowInfo.and(kotlinCall.psiKotlinCall.resultDataFlowInfo)
} }
protected abstract fun argumentToParameterMap( abstract fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor, resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>, valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
): Map<ValueArgument, ArgumentMatchImpl> ): Map<ValueArgument, ArgumentMatchImpl>
@@ -130,5 +139,4 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D>
} }
} }
}.compactIfPossible() }.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.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class NewResolvedCallImpl<D : CallableDescriptor>( class NewResolvedCallImpl<D : CallableDescriptor>(
val resolvedCallAtom: ResolvedCallAtom, override val resolvedCallAtom: ResolvedCallAtom,
substitutor: NewTypeSubstitutor?, substitutor: NewTypeSubstitutor?,
private var diagnostics: Collection<KotlinCallDiagnostic>, private var diagnostics: Collection<KotlinCallDiagnostic>,
private val typeApproximator: TypeApproximator, private val typeApproximator: TypeApproximator,
override val languageVersionSettings: LanguageVersionSettings, override val languageVersionSettings: LanguageVersionSettings,
) : NewAbstractResolvedCall<D>() { ) : NewAbstractResolvedCall<D>() {
var isCompleted = false override val psiKotlinCall: PSIKotlinCall = resolvedCallAtom.atom.psiKotlinCall
override var isCompleted = false
private set private set
private lateinit var resultingDescriptor: D private lateinit var resultingDescriptor: D
@@ -104,7 +105,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
dispatchReceiver = dispatchReceiver?.replaceType(newType) dispatchReceiver = dispatchReceiver?.replaceType(newType)
} }
fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) { override fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
//clear cached values //clear cached values
argumentToParameterMap = null argumentToParameterMap = null
_valueArguments = null _valueArguments = null
@@ -192,8 +193,12 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
// TODO: merge last two substitutors to avoid redundant descriptor substitutions // TODO: merge last two substitutors to avoid redundant descriptor substitutions
return substitute(resolvedCallAtom.freshVariablesSubstitutor).substitute(resolvedCallAtom.knownParametersSubstitutor) return substitute(resolvedCallAtom.freshVariablesSubstitutor)
.substituteAndApproximateTypes(inferredTypeVariablesSubstitutor, if (shouldApproximate) typeApproximator else null) .substitute(resolvedCallAtom.knownParametersSubstitutor)
.substituteAndApproximateTypes(
inferredTypeVariablesSubstitutor,
typeApproximator.takeIf { shouldApproximate }
)
} }
fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? { 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.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor 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.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
class NewVariableAsFunctionResolvedCallImpl( class NewVariableAsFunctionResolvedCallImpl(
override val variableCall: NewResolvedCallImpl<VariableDescriptor>, override val variableCall: NewAbstractResolvedCall<VariableDescriptor>,
override val functionCall: NewResolvedCallImpl<FunctionDescriptor>, override val functionCall: NewAbstractResolvedCall<FunctionDescriptor>,
) : VariableAsFunctionResolvedCall, ResolvedCall<FunctionDescriptor> by functionCall { ) : VariableAsFunctionResolvedCall, NewAbstractResolvedCall<FunctionDescriptor>() {
val baseCall get() = functionCall.resolvedCallAtom.atom.psiKotlinCall.cast<PSIKotlinCallForInvoke>().baseCall 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
} }