From fc0058d471a4d8faac143f2922daadebd3b221a6 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 12 Sep 2022 11:28:43 +0200 Subject: [PATCH] Revert "[FE 1.0] Resolve constructor calls through the new type inference infra" This reverts commit 0070c234ce814a5ed4ef933313423f2d88f3ee36. --- .../kotlin/resolve/calls/CallResolver.java | 81 ++++++++----- .../resolve/calls/tower/PSICallResolver.kt | 7 +- .../resolve/calls/util/CallResolverUtil.kt | 109 ++++++++---------- .../nestedExtendsInner.kt | 2 +- 4 files changed, 103 insertions(+), 96 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index 06695680822..fd6f0a438cc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.resolve.calls; import com.intellij.psi.PsiElement; +import kotlin.Pair; import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,6 +17,7 @@ import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; +import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; @@ -307,8 +309,7 @@ public class CallResolver { callResolutionContext, Collections.singletonList(descriptor), tracingStrategy, - substitutor, - null + substitutor ); } @@ -353,7 +354,7 @@ public class CallResolver { NewResolutionOldInference.ResolutionKind.Function.INSTANCE); } else if (calleeExpression instanceof KtConstructorCalleeExpression) { - return (OverloadResolutionResults) resolveConstructorCall(context, (KtConstructorCalleeExpression) calleeExpression); + return (OverloadResolutionResults) resolveCallForConstructor(context, (KtConstructorCalleeExpression) calleeExpression); } else if (calleeExpression instanceof KtConstructorDelegationReferenceExpression) { KtConstructorDelegationCall delegationCall = (KtConstructorDelegationCall) context.call.getCallElement(); @@ -392,7 +393,7 @@ public class CallResolver { return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke); } - public OverloadResolutionResults resolveConstructorCall( + private OverloadResolutionResults resolveCallForConstructor( @NotNull BasicCallResolutionContext context, @NotNull KtConstructorCalleeExpression expression ) { @@ -426,27 +427,22 @@ public class CallResolver { return checkArgumentTypesAndFail(context); } - return resolveTypeParametersAwaringConstructorCall(context, constructedType, TracingStrategyImpl.create(functionReference, context.call)); + return resolveConstructorCall(context, functionReference, constructedType); } @NotNull - public OverloadResolutionResults resolveTypeParametersAwaringConstructorCall( + public OverloadResolutionResults resolveConstructorCall( @NotNull BasicCallResolutionContext context, - @NotNull KotlinType constructedType, - @NotNull TracingStrategy tracingStrategy + @NotNull KtReferenceExpression functionReference, + @NotNull KotlinType constructedType ) { - // If any constructor has type parameter (currently it only can be true for ones from Java), try to infer arguments for them - // Otherwise use NO_EXPECTED_TYPE and known type substitutor - boolean anyConstructorHasDeclaredTypeParameters = - anyConstructorHasDeclaredTypeParameters(constructedType.getConstructor().getDeclarationDescriptor()); + Pair>, BasicCallResolutionContext> candidatesAndContext = + prepareCandidatesAndContextForConstructorCall(constructedType, context, syntheticScopes); - if (anyConstructorHasDeclaredTypeParameters) { - context = context.replaceExpectedType(constructedType); - } + Collection> candidates = candidatesAndContext.getFirst(); + context = candidatesAndContext.getSecond(); - return CallResolverUtilKt.resolveConstructorCallWithGivenDescriptors( - PSICallResolver, context, constructedType, !anyConstructorHasDeclaredTypeParameters, syntheticScopes, tracingStrategy - ); + return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates); } @Nullable @@ -496,11 +492,11 @@ public class CallResolver { @NotNull private OverloadResolutionResults resolveConstructorDelegationCall( @NotNull BasicCallResolutionContext context, - @NotNull KtConstructorDelegationCall callElement, + @NotNull KtConstructorDelegationCall call, @NotNull KtConstructorDelegationReferenceExpression calleeExpression, @NotNull ClassDescriptor currentClassDescriptor ) { - context.trace.record(BindingContext.LEXICAL_SCOPE, callElement, context.scope); + context.trace.record(BindingContext.LEXICAL_SCOPE, call, context.scope); boolean isThisCall = calleeExpression.isThis(); if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !isThisCall) { @@ -518,7 +514,7 @@ public class CallResolver { PsiElement reportOn = calcReportOn(calleeExpression); context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(reportOn)); } - if (callElement.isImplicit()) return OverloadResolutionResultsImpl.nameNotFound(); + if (call.isImplicit()) return OverloadResolutionResultsImpl.nameNotFound(); } if (constructors.isEmpty()) { @@ -530,14 +526,16 @@ public class CallResolver { KotlinType superType = isThisCall ? currentClassDescriptor.getDefaultType() : DescriptorUtils.getSuperClassType(currentClassDescriptor); - TracingStrategy tracingStrategy = callElement.isImplicit() ? - new TracingStrategyForImplicitConstructorDelegationCall(callElement, context.call) : + Pair>, BasicCallResolutionContext> candidatesAndContext = + prepareCandidatesAndContextForConstructorCall(superType, context, syntheticScopes); + Collection> candidates = candidatesAndContext.getFirst(); + context = candidatesAndContext.getSecond(); + + TracingStrategy tracing = call.isImplicit() ? + new TracingStrategyForImplicitConstructorDelegationCall(call, context.call) : TracingStrategyImpl.create(calleeExpression, context.call); - OverloadResolutionResults resolutionResults = - resolveTypeParametersAwaringConstructorCall(context, superType, tracingStrategy); - - PsiElement reportOn = callElement.isImplicit() ? callElement : calleeExpression; + PsiElement reportOn = call.isImplicit() ? call : calleeExpression; if (delegateClassDescriptor.isInner() && !DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, reportOn, @@ -545,7 +543,7 @@ public class CallResolver { return checkArgumentTypesAndFail(context); } - return resolutionResults; + return computeTasksFromCandidatesAndResolvedCall(context, candidates, tracing); } @Nullable @@ -554,6 +552,33 @@ public class CallResolver { return CallResolverUtilKt.reportOnElement(delegationCall); } + @NotNull + private static Pair>, BasicCallResolutionContext> prepareCandidatesAndContextForConstructorCall( + @NotNull KotlinType superType, + @NotNull BasicCallResolutionContext context, + @NotNull SyntheticScopes syntheticScopes + ) { + if (!(superType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) { + return new Pair<>(Collections.>emptyList(), context); + } + + // If any constructor has type parameter (currently it only can be true for ones from Java), try to infer arguments for them + // Otherwise use NO_EXPECTED_TYPE and known type substitutor + boolean anyConstructorHasDeclaredTypeParameters = + anyConstructorHasDeclaredTypeParameters(superType.getConstructor().getDeclarationDescriptor()); + + if (anyConstructorHasDeclaredTypeParameters) { + context = context.replaceExpectedType(superType); + } + + List> candidates = + CallResolverUtilKt.createResolutionCandidatesForConstructors( + context.scope, context.call, superType, !anyConstructorHasDeclaredTypeParameters, syntheticScopes + ); + + return new Pair<>(candidates, context); + } + private static boolean anyConstructorHasDeclaredTypeParameters(@Nullable ClassifierDescriptor classDescriptor) { if (!(classDescriptor instanceof ClassDescriptor)) return false; for (ConstructorDescriptor constructor : ((ClassDescriptor) classDescriptor).getConstructors()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index 02692695d16..2429abf4679 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -148,19 +148,18 @@ class PSICallResolver( context: BasicCallResolutionContext, descriptors: Collection, tracingStrategy: TracingStrategy, - substitutor: TypeSubstitutor? = null, - receiver: ReceiverValueWithSmartCastInfo? = null + substitutor: TypeSubstitutor? = null ): OverloadResolutionResults { val isSpecialFunction = descriptors.any { it.name in SPECIAL_FUNCTION_NAMES } val kotlinCall = toKotlinCall( - context, KotlinCallKind.FUNCTION, context.call, givenCandidatesName, tracingStrategy, isSpecialFunction, receiver?.receiverValue + context, KotlinCallKind.FUNCTION, context.call, givenCandidatesName, tracingStrategy, isSpecialFunction, null ) val scopeTower = ASTScopeTower(context) val resolutionCallbacks = createResolutionCallbacks(context) val givenCandidates = descriptors.map { GivenCandidate( it, - dispatchReceiver = receiver, + dispatchReceiver = null, knownTypeParametersResultingSubstitutor = substitutor ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallResolverUtil.kt index 7cde5004fa2..5a115c85bf9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallResolverUtil.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks @@ -32,8 +31,8 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstituto import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables import org.jetbrains.kotlin.resolve.calls.model.* -import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults -import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy +import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind +import org.jetbrains.kotlin.resolve.calls.tasks.OldResolutionCandidate import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation import org.jetbrains.kotlin.resolve.scopes.LexicalScope @@ -44,10 +43,10 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.error.ErrorUtils import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.error.ErrorScopeKind -import org.jetbrains.kotlin.types.error.ErrorUtils import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.util.buildNotFixedVariablesToPossibleResultType @@ -283,73 +282,57 @@ fun isArrayOrArrayLiteral(argument: ValueArgument, trace: BindingTrace): Boolean return KotlinBuiltIns.isArrayOrPrimitiveArray(type) } -private fun computeConstructorDescriptorsToResolveAndReceiver( - constructors: Collection, - containingClass: ClassDescriptor, - scope: LexicalScope, - substitutor: TypeSubstitutor?, +fun createResolutionCandidatesForConstructors( + lexicalScope: LexicalScope, + call: Call, + typeWithConstructors: KotlinType, + useKnownTypeSubstitutor: Boolean, syntheticScopes: SyntheticScopes -): Pair, ReceiverValue?>? { - val dispatchReceiver: ReceiverValue? = if (containingClass.isInner) { - val outerClassType = (containingClass.containingDeclaration as? ClassDescriptor)?.defaultType ?: return null - val substitutedOuterClassType = substitutor?.substitute(outerClassType, Variance.INVARIANT) ?: outerClassType - val receiver = scope.getImplicitReceiversHierarchy().firstOrNull { - KotlinTypeChecker.DEFAULT.isSubtypeOf(it.type, substitutedOuterClassType) - } ?: return null +): List> { + val classWithConstructors = typeWithConstructors.constructor.declarationDescriptor as ClassDescriptor - receiver.value + val unwrappedType = typeWithConstructors.unwrap() + val knownSubstitutor = + if (useKnownTypeSubstitutor) + TypeSubstitutor.create( + (unwrappedType as? AbbreviatedType)?.abbreviation ?: unwrappedType + ) + else null + + val typeAliasDescriptor = + if (unwrappedType is AbbreviatedType) + unwrappedType.abbreviation.constructor.declarationDescriptor as? TypeAliasDescriptor + else + null + + val constructors = typeAliasDescriptor?.constructors?.mapNotNull(TypeAliasConstructorDescriptor::withDispatchReceiver) + ?: classWithConstructors.constructors + + if (constructors.isEmpty()) return emptyList() + + val receiverKind: ExplicitReceiverKind + val dispatchReceiver: ReceiverValue? + + if (classWithConstructors.isInner) { + val outerClassType = (classWithConstructors.containingDeclaration as? ClassDescriptor)?.defaultType ?: return emptyList() + val substitutedOuterClassType = knownSubstitutor?.substitute(outerClassType, Variance.INVARIANT) ?: outerClassType + + val receiver = lexicalScope.getImplicitReceiversHierarchy().firstOrNull { + KotlinTypeChecker.DEFAULT.isSubtypeOf(it.type, substitutedOuterClassType) + } ?: return emptyList() + + receiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER + dispatchReceiver = receiver.value } else { - null + receiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER + dispatchReceiver = null } val syntheticConstructors = constructors.flatMap { syntheticScopes.collectSyntheticConstructors(it) } - return constructors + syntheticConstructors to dispatchReceiver - -} - -fun resolveConstructorCallWithGivenDescriptors( - PSICallResolver: PSICallResolver, - context: BasicCallResolutionContext, - constructorType: KotlinType, - useKnownTypeSubstitutor: Boolean, - syntheticScopes: SyntheticScopes, - tracingStrategy: TracingStrategy -): OverloadResolutionResults { - val containingClass = constructorType.constructor.declarationDescriptor as ClassDescriptor - - @Suppress("NAME_SHADOWING") - val constructorType = constructorType.unwrap() - val knownSubstitutor = if (useKnownTypeSubstitutor) { - TypeSubstitutor.create((constructorType as? AbbreviatedType)?.abbreviation ?: constructorType) - } else null - val typeAliasDescriptor = if (constructorType is AbbreviatedType) { - constructorType.abbreviation.constructor.declarationDescriptor as? TypeAliasDescriptor - } else null - - val (constructors, receiver) = computeConstructorDescriptorsToResolveAndReceiver( - constructors = typeAliasDescriptor?.constructors?.mapNotNull(TypeAliasConstructorDescriptor::withDispatchReceiver) - ?: containingClass.constructors, - containingClass, - context.scope, - knownSubstitutor, - syntheticScopes - ) ?: (emptyList() to null) - - val resolutionResults = PSICallResolver.runResolutionAndInferenceForGivenDescriptors( - context, - constructors, - tracingStrategy, - knownSubstitutor, - receiver?.let { context.transformToReceiverWithSmartCastInfo(it) } - ) - - if (resolutionResults.isSingleResult) { - context.trace.record(BindingContext.RESOLVED_CALL, context.call, resolutionResults.resultingCall) - context.trace.record(BindingContext.CALL, context.call.calleeExpression ?: context.call.callElement, context.call) + return (constructors + syntheticConstructors).map { + OldResolutionCandidate.create(call, it, dispatchReceiver, receiverKind, knownSubstitutor) } - - return resolutionResults } internal fun PsiElement.reportOnElement() = diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/nestedExtendsInner.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/nestedExtendsInner.kt index 603d71739f1..45dfbf44d3c 100644 --- a/compiler/testData/diagnostics/tests/secondaryConstructors/nestedExtendsInner.kt +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/nestedExtendsInner.kt @@ -2,6 +2,6 @@ class A { open inner class Inner class Nested : Inner { - constructor() + constructor() } }