NI: some review fixes for improved postponed arguments analysis

This commit is contained in:
Victor Petukhov
2020-05-25 12:41:38 +03:00
parent 756326cefe
commit e70242f6f1
3 changed files with 29 additions and 30 deletions
@@ -111,10 +111,13 @@ class KotlinConstraintSystemCompleter(
TypeVariableDependencyInformationProvider(notFixedTypeVariables, postponedArguments, topLevelType, this) TypeVariableDependencyInformationProvider(notFixedTypeVariables, postponedArguments, topLevelType, this)
// Stage 2: collect parameter types for postponed arguments // Stage 2: collect parameter types for postponed arguments
postponedArgumentInputTypesResolver.collectParameterTypesAndBuildNewExpectedTypes( val wasBuiltNewExpectedTypeForSomeArgument = postponedArgumentInputTypesResolver.collectParameterTypesAndBuildNewExpectedTypes(
asPostponedArgumentInputTypesResolverContext(), postponedArgumentsWithRevisableType, completionMode, dependencyProvider asPostponedArgumentInputTypesResolverContext(), postponedArgumentsWithRevisableType, completionMode, dependencyProvider
) )
if (wasBuiltNewExpectedTypeForSomeArgument)
continue
if (completionMode == ConstraintSystemCompletionMode.FULL) { if (completionMode == ConstraintSystemCompletionMode.FULL) {
// Stage 3: fix variables for parameter types of all postponed arguments // Stage 3: fix variables for parameter types of all postponed arguments
for (argument in postponedArguments) { for (argument in postponedArguments) {
@@ -133,32 +136,29 @@ class KotlinConstraintSystemCompleter(
// Stage 4: create atoms with revised expected types if needed // Stage 4: create atoms with revised expected types if needed
for (argument in postponedArgumentsWithRevisableType) { for (argument in postponedArgumentsWithRevisableType) {
postponedArgumentInputTypesResolver.transformToAtomWithNewFunctionalExpectedType( val wasTransformedSomeArgument = postponedArgumentInputTypesResolver.transformToAtomWithNewFunctionalExpectedType(
asPostponedArgumentInputTypesResolverContext(), argument, diagnosticsHolder 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 // Stage 5: analyze the next ready postponed argument
if (analyzeNextReadyPostponedArgument(revisedPostponedArguments, completionMode, analyze)) if (analyzeNextReadyPostponedArgument(postponedArguments, completionMode, analyze))
continue continue
// Stage 6: fix type variables fix if possible or report not enough information (if completion mode is full) // Stage 6: fix type variables fix if possible or report not enough information (if completion mode is full)
val wasFixedSomeVariable = fixVariablesOrReportNotEnoughInformation( val wasFixedSomeVariable = fixVariablesOrReportNotEnoughInformation(
completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, revisedPostponedArguments, diagnosticsHolder completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, postponedArguments, diagnosticsHolder
) )
if (wasFixedSomeVariable) if (wasFixedSomeVariable)
continue continue
// Stage 7: force analysis of remaining not analyzed postponed arguments and rerun stages if there are // Stage 7: force analysis of remaining not analyzed postponed arguments and rerun stages if there are
if (completionMode == ConstraintSystemCompletionMode.FULL) { if (completionMode == ConstraintSystemCompletionMode.FULL) {
if (analyzeRemainingNotAnalyzedPostponedArgument(revisedPostponedArguments, analyze)) if (analyzeRemainingNotAnalyzedPostponedArgument(postponedArguments, analyze))
continue continue
} }
@@ -304,7 +304,7 @@ class PostponedArgumentInputTypesResolver(
else -> parameterTypesInfo.annotations else -> parameterTypesInfo.annotations
} }
val nexExpectedType = KotlinTypeFactory.simpleType( val newExpectedType = KotlinTypeFactory.simpleType(
annotations, annotations,
functionalConstructor, functionalConstructor,
variablesForParameterTypes + variableForReturnType.defaultType.asTypeProjection(), variablesForParameterTypes + variableForReturnType.defaultType.asTypeProjection(),
@@ -312,12 +312,12 @@ class PostponedArgumentInputTypesResolver(
) )
getBuilder().addSubtypeConstraint( getBuilder().addSubtypeConstraint(
nexExpectedType, newExpectedType,
expectedType, expectedType,
ArgumentConstraintPosition(argument.atom) ArgumentConstraintPosition(argument.atom)
) )
return nexExpectedType return newExpectedType
} }
fun collectParameterTypesAndBuildNewExpectedTypes( fun collectParameterTypesAndBuildNewExpectedTypes(
@@ -325,7 +325,7 @@ class PostponedArgumentInputTypesResolver(
postponedArguments: List<PostponedAtomWithRevisableExpectedType>, postponedArguments: List<PostponedAtomWithRevisableExpectedType>,
completionMode: KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode, completionMode: KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode,
dependencyProvider: TypeVariableDependencyInformationProvider dependencyProvider: TypeVariableDependencyInformationProvider
) { ): Boolean {
// We can collect parameter types from declaration in any mode, they can't change during completion. // We can collect parameter types from declaration in any mode, they can't change during completion.
val postponedArgumentsToCollectTypesFromDeclaredParameters = postponedArguments val postponedArgumentsToCollectTypesFromDeclaredParameters = postponedArguments
.filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>() .filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>()
@@ -349,27 +349,24 @@ class PostponedArgumentInputTypesResolver(
postponedArguments postponedArguments
} }
do { return postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType.filter { it.revisedExpectedType == null }.any { argument ->
val wasTransformedSomePostponedArgument = val parameterTypesInfo =
postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType.filter { it.revisedExpectedType == null }.any { argument -> c.extractParameterTypesInfo(argument, postponedArguments, dependencyProvider) ?: return@any false
val parameterTypesInfo = val newExpectedType =
c.extractParameterTypesInfo(argument, postponedArguments, dependencyProvider) ?: return@any false c.buildNewFunctionalExpectedType(argument, parameterTypesInfo) ?: return@any false
val newExpectedType =
c.buildNewFunctionalExpectedType(argument, parameterTypesInfo) ?: return@any false
argument.revisedExpectedType = newExpectedType argument.revisedExpectedType = newExpectedType
true true
} }
} while (wasTransformedSomePostponedArgument)
} }
fun transformToAtomWithNewFunctionalExpectedType( fun transformToAtomWithNewFunctionalExpectedType(
c: Context, c: Context,
argument: PostponedAtomWithRevisableExpectedType, argument: PostponedAtomWithRevisableExpectedType,
diagnosticsHolder: KotlinDiagnosticsHolder diagnosticsHolder: KotlinDiagnosticsHolder
) { ): Boolean {
val revisedExpectedType = argument.revisedExpectedType?.takeIf { it.isFunctionOrKFunctionTypeWithAnySuspendability } ?: return val revisedExpectedType = argument.revisedExpectedType?.takeIf { it.isFunctionOrKFunctionTypeWithAnySuspendability } ?: return false
when (argument) { when (argument) {
is PostponedCallableReferenceAtom -> is PostponedCallableReferenceAtom ->
@@ -380,6 +377,8 @@ class PostponedArgumentInputTypesResolver(
argument.transformToResolvedLambda(c.getBuilder(), diagnosticsHolder, revisedExpectedType) argument.transformToResolvedLambda(c.getBuilder(), diagnosticsHolder, revisedExpectedType)
else -> throw IllegalStateException("Unsupported postponed argument type of $argument") else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
} }
return true
} }
private fun getAllDeeplyRelatedTypeVariables( private fun getAllDeeplyRelatedTypeVariables(
@@ -119,8 +119,8 @@ fun main() {
* K <: (A) -> Unit -> TypeVariable(_RP1) >: A * K <: (A) -> Unit -> TypeVariable(_RP1) >: A
* K >: (C) -> TypeVariable(_R) -> TypeVariable(_RP1) <: C * K >: (C) -> TypeVariable(_R) -> TypeVariable(_RP1) <: C
*/ */
val x12 = selectC(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x: B -> }<!><!NO_VALUE_FOR_PARAMETER!>)<!> val x12 = selectC(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x: B -> }<!><!NO_VALUE_FOR_PARAMETER!>)<!>
val x13 = selectA(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x: C -> }<!><!NO_VALUE_FOR_PARAMETER!>)<!> val x13 = selectA(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x: C -> }<!><!NO_VALUE_FOR_PARAMETER!>)<!>
val x14 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, id { x: A -> }, { x -> x }) val x14 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, id { x: A -> }, { x -> x })
val x15 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, { x: A -> }, id { x -> x }) val x15 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, { x: A -> }, id { x -> x })
/* /*