[NI] Don't try inferring variables for effectively empty system

This commit is contained in:
Mikhail Zarechenskiy
2020-02-25 09:35:09 +03:00
parent fe71d5256c
commit 0b9fc1541d
2 changed files with 50 additions and 11 deletions
@@ -109,14 +109,12 @@ class CoroutineInferenceSession(
initialStorage: ConstraintStorage, initialStorage: ConstraintStorage,
diagnosticsHolder: KotlinDiagnosticsHolder diagnosticsHolder: KotlinDiagnosticsHolder
): Map<TypeConstructor, UnwrappedType>? { ): Map<TypeConstructor, UnwrappedType>? {
if (partiallyResolvedCallsInfo.isEmpty() && commonCalls.isEmpty()) { val (commonSystem, effectivelyEmptyConstraintSystem) = buildCommonSystem(initialStorage)
val emptyCommonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns) if (effectivelyEmptyConstraintSystem) {
updateCalls(lambda, emptyCommonSystem) updateCalls(lambda, commonSystem)
return null return null
} }
val commonSystem = buildCommonSystem(initialStorage)
val context = commonSystem.asConstraintSystemCompleterContext() val context = commonSystem.asConstraintSystemCompleterContext()
kotlinConstraintSystemCompleter.completeConstraintSystem( kotlinConstraintSystemCompleter.completeConstraintSystem(
context, context,
@@ -146,7 +144,7 @@ class CoroutineInferenceSession(
storage: ConstraintStorage, storage: ConstraintStorage,
nonFixedToVariablesSubstitutor: NewTypeSubstitutor, nonFixedToVariablesSubstitutor: NewTypeSubstitutor,
shouldIntegrateAllConstraints: Boolean shouldIntegrateAllConstraints: Boolean
) { ): Boolean {
storage.notFixedTypeVariables.values.forEach { commonSystem.registerVariable(it.typeVariable) } storage.notFixedTypeVariables.values.forEach { commonSystem.registerVariable(it.typeVariable) }
/* /*
@@ -158,12 +156,16 @@ class CoroutineInferenceSession(
* */ * */
val callSubstitutor = storage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false) val callSubstitutor = storage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false)
var introducedConstraint = false
for (initialConstraint in storage.initialConstraints) { for (initialConstraint in storage.initialConstraints) {
val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB
val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)) // TODO: SUB val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)) // TODO: SUB
if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue
introducedConstraint = true
when (initialConstraint.constraintKind) { when (initialConstraint.constraintKind) {
ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER") ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER")
@@ -182,28 +184,38 @@ class CoroutineInferenceSession(
val typeVariable = storage.allTypeVariables.getValue(variableConstructor) val typeVariable = storage.allTypeVariables.getValue(variableConstructor)
commonSystem.registerVariable(typeVariable) commonSystem.registerVariable(typeVariable)
commonSystem.addEqualityConstraint((typeVariable as NewTypeVariable).defaultType, type, CoroutinePosition()) commonSystem.addEqualityConstraint((typeVariable as NewTypeVariable).defaultType, type, CoroutinePosition())
introducedConstraint = true
} }
} }
return introducedConstraint
} }
private fun buildCommonSystem(initialStorage: ConstraintStorage): NewConstraintSystemImpl { private fun buildCommonSystem(initialStorage: ConstraintStorage): Pair<NewConstraintSystemImpl, Boolean> {
val commonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns) val commonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns)
val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor() val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor()
integrateConstraints(commonSystem, initialStorage, nonFixedToVariablesSubstitutor, false) integrateConstraints(commonSystem, initialStorage, nonFixedToVariablesSubstitutor, false)
var effectivelyEmptyCommonSystem = true
for (call in commonCalls) { 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) { 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) { for (diagnostic in diagnostics) {
commonSystem.addError(diagnostic) commonSystem.addError(diagnostic)
} }
return commonSystem return commonSystem to effectivelyEmptyCommonSystem
} }
private fun updateCalls(lambda: ResolvedLambdaAtom, commonSystem: NewConstraintSystemImpl) { private fun updateCalls(lambda: ResolvedLambdaAtom, commonSystem: NewConstraintSystemImpl) {
@@ -12,7 +12,29 @@ fun test() {
flow { flow {
emit(1) emit(1)
}.flatMapLatest<Int, Long> { }.flatMapLatest<Int, Long> {
flow {} flow {
expectInt(42)
}
}
flow {
emit(1)
}.flatMapLatest<Int, Long> {
flow {
expectInt(42)
hang {
expectInt(0)
}
}
}
flow {
emit(1)
}.flatMap {
if (it == 1)
flow { expectGeneric(42) }
else
flow<Int> {}
} }
flow { flow {
@@ -33,6 +55,11 @@ fun test() {
} }
} }
fun expectInt(i: Int) {}
fun <K> expectGeneric(i: K) {}
suspend inline fun hang(onCancellation: () -> Unit) {}
fun <T> Flow<T>.flatMap(mapper: suspend (T) -> Flow<T>): Flow<T> = TODO() fun <T> Flow<T>.flatMap(mapper: suspend (T) -> Flow<T>): Flow<T> = TODO()
@OptIn(ExperimentalTypeInference::class) @OptIn(ExperimentalTypeInference::class)