diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt index a53eee72608..00da2d72a6b 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt @@ -111,10 +111,13 @@ class KotlinConstraintSystemCompleter( TypeVariableDependencyInformationProvider(notFixedTypeVariables, postponedArguments, topLevelType, this) // Stage 2: collect parameter types for postponed arguments - postponedArgumentInputTypesResolver.collectParameterTypesAndBuildNewExpectedTypes( + val wasBuiltNewExpectedTypeForSomeArgument = postponedArgumentInputTypesResolver.collectParameterTypesAndBuildNewExpectedTypes( asPostponedArgumentInputTypesResolverContext(), postponedArgumentsWithRevisableType, completionMode, dependencyProvider ) + if (wasBuiltNewExpectedTypeForSomeArgument) + continue + if (completionMode == ConstraintSystemCompletionMode.FULL) { // Stage 3: fix variables for parameter types of all postponed arguments for (argument in postponedArguments) { @@ -133,32 +136,29 @@ class KotlinConstraintSystemCompleter( // Stage 4: create atoms with revised expected types if needed for (argument in postponedArgumentsWithRevisableType) { - postponedArgumentInputTypesResolver.transformToAtomWithNewFunctionalExpectedType( + val wasTransformedSomeArgument = postponedArgumentInputTypesResolver.transformToAtomWithNewFunctionalExpectedType( asPostponedArgumentInputTypesResolverContext(), argument, diagnosticsHolder ) + + if (wasTransformedSomeArgument) + continue@completion } } - /* - * We should get not analyzed postponed arguments again because they can be changed by - * the stage of fixation type variables for parameters or analysing postponed arguments with fixed parameter types (see stage #1 and #4) - */ - val revisedPostponedArguments = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms) - // Stage 5: analyze the next ready postponed argument - if (analyzeNextReadyPostponedArgument(revisedPostponedArguments, completionMode, analyze)) + if (analyzeNextReadyPostponedArgument(postponedArguments, completionMode, analyze)) continue // Stage 6: fix type variables – fix if possible or report not enough information (if completion mode is full) val wasFixedSomeVariable = fixVariablesOrReportNotEnoughInformation( - completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, revisedPostponedArguments, diagnosticsHolder + completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, postponedArguments, diagnosticsHolder ) if (wasFixedSomeVariable) continue // Stage 7: force analysis of remaining not analyzed postponed arguments and rerun stages if there are if (completionMode == ConstraintSystemCompletionMode.FULL) { - if (analyzeRemainingNotAnalyzedPostponedArgument(revisedPostponedArguments, analyze)) + if (analyzeRemainingNotAnalyzedPostponedArgument(postponedArguments, analyze)) continue } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/PostponedArgumentInputTypesResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/PostponedArgumentInputTypesResolver.kt index 695b97f21a2..7bf47656283 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/PostponedArgumentInputTypesResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/PostponedArgumentInputTypesResolver.kt @@ -304,7 +304,7 @@ class PostponedArgumentInputTypesResolver( else -> parameterTypesInfo.annotations } - val nexExpectedType = KotlinTypeFactory.simpleType( + val newExpectedType = KotlinTypeFactory.simpleType( annotations, functionalConstructor, variablesForParameterTypes + variableForReturnType.defaultType.asTypeProjection(), @@ -312,12 +312,12 @@ class PostponedArgumentInputTypesResolver( ) getBuilder().addSubtypeConstraint( - nexExpectedType, + newExpectedType, expectedType, ArgumentConstraintPosition(argument.atom) ) - return nexExpectedType + return newExpectedType } fun collectParameterTypesAndBuildNewExpectedTypes( @@ -325,7 +325,7 @@ class PostponedArgumentInputTypesResolver( postponedArguments: List, completionMode: KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode, dependencyProvider: TypeVariableDependencyInformationProvider - ) { + ): Boolean { // We can collect parameter types from declaration in any mode, they can't change during completion. val postponedArgumentsToCollectTypesFromDeclaredParameters = postponedArguments .filterIsInstance() @@ -349,27 +349,24 @@ class PostponedArgumentInputTypesResolver( postponedArguments } - do { - val wasTransformedSomePostponedArgument = - postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType.filter { it.revisedExpectedType == null }.any { argument -> - val parameterTypesInfo = - c.extractParameterTypesInfo(argument, postponedArguments, dependencyProvider) ?: return@any false - val newExpectedType = - c.buildNewFunctionalExpectedType(argument, parameterTypesInfo) ?: return@any false + return postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType.filter { it.revisedExpectedType == null }.any { argument -> + val parameterTypesInfo = + c.extractParameterTypesInfo(argument, postponedArguments, dependencyProvider) ?: return@any false + val newExpectedType = + c.buildNewFunctionalExpectedType(argument, parameterTypesInfo) ?: return@any false - argument.revisedExpectedType = newExpectedType + argument.revisedExpectedType = newExpectedType - true - } - } while (wasTransformedSomePostponedArgument) + true + } } fun transformToAtomWithNewFunctionalExpectedType( c: Context, argument: PostponedAtomWithRevisableExpectedType, diagnosticsHolder: KotlinDiagnosticsHolder - ) { - val revisedExpectedType = argument.revisedExpectedType?.takeIf { it.isFunctionOrKFunctionTypeWithAnySuspendability } ?: return + ): Boolean { + val revisedExpectedType = argument.revisedExpectedType?.takeIf { it.isFunctionOrKFunctionTypeWithAnySuspendability } ?: return false when (argument) { is PostponedCallableReferenceAtom -> @@ -380,6 +377,8 @@ class PostponedArgumentInputTypesResolver( argument.transformToResolvedLambda(c.getBuilder(), diagnosticsHolder, revisedExpectedType) else -> throw IllegalStateException("Unsupported postponed argument type of $argument") } + + return true } private fun getAllDeeplyRelatedTypeVariables( diff --git a/compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.kt b/compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.kt index 376b81c8f35..07c7cc5a200 100644 --- a/compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.kt +++ b/compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.kt @@ -119,8 +119,8 @@ fun main() { * K <: (A) -> Unit -> TypeVariable(_RP1) >: A * K >: (C) -> TypeVariable(_R) -> TypeVariable(_RP1) <: C */ - val x12 = selectC(id { it }, id { x: B -> }) - val x13 = selectA(id { it }, id { x: C -> }) + val x12 = selectC(id { it }, id { x: B -> }) + val x13 = selectA(id { it }, id { x: C -> }) val x14 = selectC(id { it }, id { x: A -> }, { x -> x }) val x15 = selectC(id { it }, { x: A -> }, id { x -> x }) /*