From 0b9fc1541d30a1976d2f14108fb027e7ecd97dea Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 25 Feb 2020 09:35:09 +0300 Subject: [PATCH] [NI] Don't try inferring variables for effectively empty system --- .../inference/CoroutineInferenceSession.kt | 32 +++++++++++++------ ...nstraintSystemForCoroutineInferenceCall.kt | 29 ++++++++++++++++- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt index 834d0522a8d..1157555d31b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt @@ -109,14 +109,12 @@ class CoroutineInferenceSession( initialStorage: ConstraintStorage, diagnosticsHolder: KotlinDiagnosticsHolder ): Map? { - if (partiallyResolvedCallsInfo.isEmpty() && commonCalls.isEmpty()) { - val emptyCommonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns) - updateCalls(lambda, emptyCommonSystem) + val (commonSystem, effectivelyEmptyConstraintSystem) = buildCommonSystem(initialStorage) + if (effectivelyEmptyConstraintSystem) { + updateCalls(lambda, commonSystem) return null } - val commonSystem = buildCommonSystem(initialStorage) - val context = commonSystem.asConstraintSystemCompleterContext() kotlinConstraintSystemCompleter.completeConstraintSystem( context, @@ -146,7 +144,7 @@ class CoroutineInferenceSession( storage: ConstraintStorage, nonFixedToVariablesSubstitutor: NewTypeSubstitutor, shouldIntegrateAllConstraints: Boolean - ) { + ): Boolean { storage.notFixedTypeVariables.values.forEach { commonSystem.registerVariable(it.typeVariable) } /* @@ -158,12 +156,16 @@ class CoroutineInferenceSession( * */ val callSubstitutor = storage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false) + var introducedConstraint = false + for (initialConstraint in storage.initialConstraints) { val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)) // TODO: SUB if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue + introducedConstraint = true + when (initialConstraint.constraintKind) { ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER") @@ -182,28 +184,38 @@ class CoroutineInferenceSession( val typeVariable = storage.allTypeVariables.getValue(variableConstructor) commonSystem.registerVariable(typeVariable) commonSystem.addEqualityConstraint((typeVariable as NewTypeVariable).defaultType, type, CoroutinePosition()) + introducedConstraint = true } } + + return introducedConstraint } - private fun buildCommonSystem(initialStorage: ConstraintStorage): NewConstraintSystemImpl { + private fun buildCommonSystem(initialStorage: ConstraintStorage): Pair { val commonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns) val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor() integrateConstraints(commonSystem, initialStorage, nonFixedToVariablesSubstitutor, false) + var effectivelyEmptyCommonSystem = true + for (call in commonCalls) { - integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, false) + val hasConstraints = + integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, false) + if (hasConstraints) effectivelyEmptyCommonSystem = false } for (call in partiallyResolvedCallsInfo) { - integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, true) + val hasConstraints = + integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, true) + if (hasConstraints) effectivelyEmptyCommonSystem = false } + for (diagnostic in diagnostics) { commonSystem.addError(diagnostic) } - return commonSystem + return commonSystem to effectivelyEmptyCommonSystem } private fun updateCalls(lambda: ResolvedLambdaAtom, commonSystem: NewConstraintSystemImpl) { diff --git a/compiler/testData/codegen/box/coroutines/emptyCommonConstraintSystemForCoroutineInferenceCall.kt b/compiler/testData/codegen/box/coroutines/emptyCommonConstraintSystemForCoroutineInferenceCall.kt index 323e354fdad..0b3cd9a4762 100644 --- a/compiler/testData/codegen/box/coroutines/emptyCommonConstraintSystemForCoroutineInferenceCall.kt +++ b/compiler/testData/codegen/box/coroutines/emptyCommonConstraintSystemForCoroutineInferenceCall.kt @@ -12,7 +12,29 @@ fun test() { flow { emit(1) }.flatMapLatest { - flow {} + flow { + expectInt(42) + } + } + + flow { + emit(1) + }.flatMapLatest { + flow { + expectInt(42) + hang { + expectInt(0) + } + } + } + + flow { + emit(1) + }.flatMap { + if (it == 1) + flow { expectGeneric(42) } + else + flow {} } flow { @@ -33,6 +55,11 @@ fun test() { } } +fun expectInt(i: Int) {} +fun expectGeneric(i: K) {} + +suspend inline fun hang(onCancellation: () -> Unit) {} + fun Flow.flatMap(mapper: suspend (T) -> Flow): Flow = TODO() @OptIn(ExperimentalTypeInference::class)