Revert "[FE 1.0] Resolve constructor calls through the new type inference infra"

This reverts commit 0070c234ce.
This commit is contained in:
Mikhail Glukhikh
2022-09-12 11:28:43 +02:00
committed by Space
parent c699896b0f
commit fc0058d471
4 changed files with 103 additions and 96 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.resolve.calls; package org.jetbrains.kotlin.resolve.calls;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import kotlin.Pair;
import kotlin.collections.CollectionsKt; import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; 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.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
@@ -307,8 +309,7 @@ public class CallResolver {
callResolutionContext, callResolutionContext,
Collections.singletonList(descriptor), Collections.singletonList(descriptor),
tracingStrategy, tracingStrategy,
substitutor, substitutor
null
); );
} }
@@ -353,7 +354,7 @@ public class CallResolver {
NewResolutionOldInference.ResolutionKind.Function.INSTANCE); NewResolutionOldInference.ResolutionKind.Function.INSTANCE);
} }
else if (calleeExpression instanceof KtConstructorCalleeExpression) { else if (calleeExpression instanceof KtConstructorCalleeExpression) {
return (OverloadResolutionResults) resolveConstructorCall(context, (KtConstructorCalleeExpression) calleeExpression); return (OverloadResolutionResults) resolveCallForConstructor(context, (KtConstructorCalleeExpression) calleeExpression);
} }
else if (calleeExpression instanceof KtConstructorDelegationReferenceExpression) { else if (calleeExpression instanceof KtConstructorDelegationReferenceExpression) {
KtConstructorDelegationCall delegationCall = (KtConstructorDelegationCall) context.call.getCallElement(); KtConstructorDelegationCall delegationCall = (KtConstructorDelegationCall) context.call.getCallElement();
@@ -392,7 +393,7 @@ public class CallResolver {
return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke); return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
} }
public OverloadResolutionResults<ConstructorDescriptor> resolveConstructorCall( private OverloadResolutionResults<ConstructorDescriptor> resolveCallForConstructor(
@NotNull BasicCallResolutionContext context, @NotNull BasicCallResolutionContext context,
@NotNull KtConstructorCalleeExpression expression @NotNull KtConstructorCalleeExpression expression
) { ) {
@@ -426,27 +427,22 @@ public class CallResolver {
return checkArgumentTypesAndFail(context); return checkArgumentTypesAndFail(context);
} }
return resolveTypeParametersAwaringConstructorCall(context, constructedType, TracingStrategyImpl.create(functionReference, context.call)); return resolveConstructorCall(context, functionReference, constructedType);
} }
@NotNull @NotNull
public OverloadResolutionResults<ConstructorDescriptor> resolveTypeParametersAwaringConstructorCall( public OverloadResolutionResults<ConstructorDescriptor> resolveConstructorCall(
@NotNull BasicCallResolutionContext context, @NotNull BasicCallResolutionContext context,
@NotNull KotlinType constructedType, @NotNull KtReferenceExpression functionReference,
@NotNull TracingStrategy tracingStrategy @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 Pair<Collection<OldResolutionCandidate<ConstructorDescriptor>>, BasicCallResolutionContext> candidatesAndContext =
// Otherwise use NO_EXPECTED_TYPE and known type substitutor prepareCandidatesAndContextForConstructorCall(constructedType, context, syntheticScopes);
boolean anyConstructorHasDeclaredTypeParameters =
anyConstructorHasDeclaredTypeParameters(constructedType.getConstructor().getDeclarationDescriptor());
if (anyConstructorHasDeclaredTypeParameters) { Collection<OldResolutionCandidate<ConstructorDescriptor>> candidates = candidatesAndContext.getFirst();
context = context.replaceExpectedType(constructedType); context = candidatesAndContext.getSecond();
}
return CallResolverUtilKt.resolveConstructorCallWithGivenDescriptors( return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates);
PSICallResolver, context, constructedType, !anyConstructorHasDeclaredTypeParameters, syntheticScopes, tracingStrategy
);
} }
@Nullable @Nullable
@@ -496,11 +492,11 @@ public class CallResolver {
@NotNull @NotNull
private OverloadResolutionResults<ConstructorDescriptor> resolveConstructorDelegationCall( private OverloadResolutionResults<ConstructorDescriptor> resolveConstructorDelegationCall(
@NotNull BasicCallResolutionContext context, @NotNull BasicCallResolutionContext context,
@NotNull KtConstructorDelegationCall callElement, @NotNull KtConstructorDelegationCall call,
@NotNull KtConstructorDelegationReferenceExpression calleeExpression, @NotNull KtConstructorDelegationReferenceExpression calleeExpression,
@NotNull ClassDescriptor currentClassDescriptor @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(); boolean isThisCall = calleeExpression.isThis();
if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !isThisCall) { if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !isThisCall) {
@@ -518,7 +514,7 @@ public class CallResolver {
PsiElement reportOn = calcReportOn(calleeExpression); PsiElement reportOn = calcReportOn(calleeExpression);
context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(reportOn)); 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()) { if (constructors.isEmpty()) {
@@ -530,14 +526,16 @@ public class CallResolver {
KotlinType superType = KotlinType superType =
isThisCall ? currentClassDescriptor.getDefaultType() : DescriptorUtils.getSuperClassType(currentClassDescriptor); isThisCall ? currentClassDescriptor.getDefaultType() : DescriptorUtils.getSuperClassType(currentClassDescriptor);
TracingStrategy tracingStrategy = callElement.isImplicit() ? Pair<Collection<OldResolutionCandidate<ConstructorDescriptor>>, BasicCallResolutionContext> candidatesAndContext =
new TracingStrategyForImplicitConstructorDelegationCall(callElement, context.call) : prepareCandidatesAndContextForConstructorCall(superType, context, syntheticScopes);
Collection<OldResolutionCandidate<ConstructorDescriptor>> candidates = candidatesAndContext.getFirst();
context = candidatesAndContext.getSecond();
TracingStrategy tracing = call.isImplicit() ?
new TracingStrategyForImplicitConstructorDelegationCall(call, context.call) :
TracingStrategyImpl.create(calleeExpression, context.call); TracingStrategyImpl.create(calleeExpression, context.call);
OverloadResolutionResults<ConstructorDescriptor> resolutionResults = PsiElement reportOn = call.isImplicit() ? call : calleeExpression;
resolveTypeParametersAwaringConstructorCall(context, superType, tracingStrategy);
PsiElement reportOn = callElement.isImplicit() ? callElement : calleeExpression;
if (delegateClassDescriptor.isInner() if (delegateClassDescriptor.isInner()
&& !DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, reportOn, && !DescriptorResolver.checkHasOuterClassInstance(context.scope, context.trace, reportOn,
@@ -545,7 +543,7 @@ public class CallResolver {
return checkArgumentTypesAndFail(context); return checkArgumentTypesAndFail(context);
} }
return resolutionResults; return computeTasksFromCandidatesAndResolvedCall(context, candidates, tracing);
} }
@Nullable @Nullable
@@ -554,6 +552,33 @@ public class CallResolver {
return CallResolverUtilKt.reportOnElement(delegationCall); return CallResolverUtilKt.reportOnElement(delegationCall);
} }
@NotNull
private static Pair<Collection<OldResolutionCandidate<ConstructorDescriptor>>, BasicCallResolutionContext> prepareCandidatesAndContextForConstructorCall(
@NotNull KotlinType superType,
@NotNull BasicCallResolutionContext context,
@NotNull SyntheticScopes syntheticScopes
) {
if (!(superType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
return new Pair<>(Collections.<OldResolutionCandidate<ConstructorDescriptor>>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<OldResolutionCandidate<ConstructorDescriptor>> candidates =
CallResolverUtilKt.createResolutionCandidatesForConstructors(
context.scope, context.call, superType, !anyConstructorHasDeclaredTypeParameters, syntheticScopes
);
return new Pair<>(candidates, context);
}
private static boolean anyConstructorHasDeclaredTypeParameters(@Nullable ClassifierDescriptor classDescriptor) { private static boolean anyConstructorHasDeclaredTypeParameters(@Nullable ClassifierDescriptor classDescriptor) {
if (!(classDescriptor instanceof ClassDescriptor)) return false; if (!(classDescriptor instanceof ClassDescriptor)) return false;
for (ConstructorDescriptor constructor : ((ClassDescriptor) classDescriptor).getConstructors()) { for (ConstructorDescriptor constructor : ((ClassDescriptor) classDescriptor).getConstructors()) {
@@ -148,19 +148,18 @@ class PSICallResolver(
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
descriptors: Collection<CallableDescriptor>, descriptors: Collection<CallableDescriptor>,
tracingStrategy: TracingStrategy, tracingStrategy: TracingStrategy,
substitutor: TypeSubstitutor? = null, substitutor: TypeSubstitutor? = null
receiver: ReceiverValueWithSmartCastInfo? = null
): OverloadResolutionResults<D> { ): OverloadResolutionResults<D> {
val isSpecialFunction = descriptors.any { it.name in SPECIAL_FUNCTION_NAMES } val isSpecialFunction = descriptors.any { it.name in SPECIAL_FUNCTION_NAMES }
val kotlinCall = toKotlinCall( 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 scopeTower = ASTScopeTower(context)
val resolutionCallbacks = createResolutionCallbacks(context) val resolutionCallbacks = createResolutionCallbacks(context)
val givenCandidates = descriptors.map { val givenCandidates = descriptors.map {
GivenCandidate( GivenCandidate(
it, it,
dispatchReceiver = receiver, dispatchReceiver = null,
knownTypeParametersResultingSubstitutor = substitutor knownTypeParametersResultingSubstitutor = substitutor
) )
} }
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks 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.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.tasks.OldResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
import org.jetbrains.kotlin.resolve.scopes.LexicalScope 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.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
import org.jetbrains.kotlin.types.* 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.TypeUtils.DONT_CARE
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.error.ErrorScopeKind 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.expressions.OperatorConventions
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.util.buildNotFixedVariablesToPossibleResultType import org.jetbrains.kotlin.util.buildNotFixedVariablesToPossibleResultType
@@ -283,73 +282,57 @@ fun isArrayOrArrayLiteral(argument: ValueArgument, trace: BindingTrace): Boolean
return KotlinBuiltIns.isArrayOrPrimitiveArray(type) return KotlinBuiltIns.isArrayOrPrimitiveArray(type)
} }
private fun computeConstructorDescriptorsToResolveAndReceiver( fun createResolutionCandidatesForConstructors(
constructors: Collection<ConstructorDescriptor>, lexicalScope: LexicalScope,
containingClass: ClassDescriptor, call: Call,
scope: LexicalScope, typeWithConstructors: KotlinType,
substitutor: TypeSubstitutor?, useKnownTypeSubstitutor: Boolean,
syntheticScopes: SyntheticScopes syntheticScopes: SyntheticScopes
): Pair<Collection<ConstructorDescriptor>, ReceiverValue?>? { ): List<OldResolutionCandidate<ConstructorDescriptor>> {
val dispatchReceiver: ReceiverValue? = if (containingClass.isInner) { val classWithConstructors = typeWithConstructors.constructor.declarationDescriptor as ClassDescriptor
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
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 { } else {
null receiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
dispatchReceiver = null
} }
val syntheticConstructors = constructors.flatMap { syntheticScopes.collectSyntheticConstructors(it) } val syntheticConstructors = constructors.flatMap { syntheticScopes.collectSyntheticConstructors(it) }
return constructors + syntheticConstructors to dispatchReceiver return (constructors + syntheticConstructors).map {
OldResolutionCandidate.create(call, it, dispatchReceiver, receiverKind, knownSubstitutor)
}
fun resolveConstructorCallWithGivenDescriptors(
PSICallResolver: PSICallResolver,
context: BasicCallResolutionContext,
constructorType: KotlinType,
useKnownTypeSubstitutor: Boolean,
syntheticScopes: SyntheticScopes,
tracingStrategy: TracingStrategy
): OverloadResolutionResults<ConstructorDescriptor> {
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<ConstructorDescriptor>() to null)
val resolutionResults = PSICallResolver.runResolutionAndInferenceForGivenDescriptors<ConstructorDescriptor>(
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 resolutionResults
} }
internal fun PsiElement.reportOnElement() = internal fun PsiElement.reportOnElement() =
@@ -2,6 +2,6 @@ class A {
open inner class Inner open inner class Inner
class Nested : Inner { class Nested : Inner {
<!INACCESSIBLE_OUTER_CLASS_EXPRESSION!>constructor()<!><!UNRESOLVED_REFERENCE!><!> <!INACCESSIBLE_OUTER_CLASS_EXPRESSION!>constructor()<!>
} }
} }