[NI] Use compatibility mode for KT-41934
This commit is contained in:
+1
-1
@@ -50,7 +50,7 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
|||||||
val postponedAtoms = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
|
val postponedAtoms = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
|
||||||
val variableForFixation =
|
val variableForFixation =
|
||||||
variableFixationFinder.findFirstVariableForFixation(
|
variableFixationFinder.findFirstVariableForFixation(
|
||||||
c, allTypeVariables, postponedAtoms, completionMode, candidateReturnType
|
c, allTypeVariables, postponedAtoms, completionMode, candidateReturnType, inferenceCompatibilityMode = true
|
||||||
) ?: break
|
) ?: break
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
+8
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.resolve.calls.inference
|
package org.jetbrains.kotlin.resolve.calls.inference
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.*
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
@@ -81,7 +82,13 @@ class CoroutineInferenceSession(
|
|||||||
return !storage.notFixedTypeVariables.keys.any {
|
return !storage.notFixedTypeVariables.keys.any {
|
||||||
val variable = storage.allTypeVariables[it]
|
val variable = storage.allTypeVariables[it]
|
||||||
val isPostponed = variable != null && variable in storage.postponedTypeVariables
|
val isPostponed = variable != null && variable in storage.postponedTypeVariables
|
||||||
!isPostponed && !kotlinConstraintSystemCompleter.variableFixationFinder.isTypeVariableHasProperConstraint(system, it)
|
val useInferenceCompatibilityMode =
|
||||||
|
topLevelCallContext.languageVersionSettings.supportsFeature(LanguageFeature.InferenceCompatibility)
|
||||||
|
!isPostponed && !kotlinConstraintSystemCompleter.variableFixationFinder.isTypeVariableHasProperConstraint(
|
||||||
|
system,
|
||||||
|
it,
|
||||||
|
useInferenceCompatibilityMode
|
||||||
|
)
|
||||||
} || candidate.getSubResolvedAtoms().any { it.hasPostponed() }
|
} || candidate.getSubResolvedAtoms().any { it.hasPostponed() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-10
@@ -32,8 +32,10 @@ class VariableFixationFinder(
|
|||||||
allTypeVariables: List<TypeConstructorMarker>,
|
allTypeVariables: List<TypeConstructorMarker>,
|
||||||
postponedKtPrimitives: List<PostponedResolvedAtomMarker>,
|
postponedKtPrimitives: List<PostponedResolvedAtomMarker>,
|
||||||
completionMode: ConstraintSystemCompletionMode,
|
completionMode: ConstraintSystemCompletionMode,
|
||||||
topLevelType: KotlinTypeMarker
|
topLevelType: KotlinTypeMarker,
|
||||||
): VariableForFixation? = c.findTypeVariableForFixation(allTypeVariables, postponedKtPrimitives, completionMode, topLevelType)
|
inferenceCompatibilityMode: Boolean = false,
|
||||||
|
): VariableForFixation? =
|
||||||
|
c.findTypeVariableForFixation(allTypeVariables, postponedKtPrimitives, completionMode, topLevelType, inferenceCompatibilityMode)
|
||||||
|
|
||||||
enum class TypeVariableFixationReadiness {
|
enum class TypeVariableFixationReadiness {
|
||||||
FORBIDDEN,
|
FORBIDDEN,
|
||||||
@@ -44,12 +46,14 @@ class VariableFixationFinder(
|
|||||||
FROM_INCORPORATION_OF_DECLARED_UPPER_BOUND,
|
FROM_INCORPORATION_OF_DECLARED_UPPER_BOUND,
|
||||||
READY_FOR_FIXATION_UPPER,
|
READY_FOR_FIXATION_UPPER,
|
||||||
READY_FOR_FIXATION_LOWER,
|
READY_FOR_FIXATION_LOWER,
|
||||||
|
READY_FOR_FIXATION,
|
||||||
READY_FOR_FIXATION_REIFIED,
|
READY_FOR_FIXATION_REIFIED,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Context.getTypeVariableReadiness(
|
private fun Context.getTypeVariableReadiness(
|
||||||
variable: TypeConstructorMarker,
|
variable: TypeConstructorMarker,
|
||||||
dependencyProvider: TypeVariableDependencyInformationProvider
|
dependencyProvider: TypeVariableDependencyInformationProvider,
|
||||||
|
inferenceCompatibilityMode: Boolean
|
||||||
): TypeVariableFixationReadiness = when {
|
): TypeVariableFixationReadiness = when {
|
||||||
!notFixedTypeVariables.contains(variable) ||
|
!notFixedTypeVariables.contains(variable) ||
|
||||||
dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN
|
dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN
|
||||||
@@ -60,16 +64,25 @@ class VariableFixationFinder(
|
|||||||
variableHasOnlyIncorporatedConstraintsFromDeclaredUpperBound(variable) ->
|
variableHasOnlyIncorporatedConstraintsFromDeclaredUpperBound(variable) ->
|
||||||
TypeVariableFixationReadiness.FROM_INCORPORATION_OF_DECLARED_UPPER_BOUND
|
TypeVariableFixationReadiness.FROM_INCORPORATION_OF_DECLARED_UPPER_BOUND
|
||||||
isReified(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_REIFIED
|
isReified(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_REIFIED
|
||||||
!variableHasLowerProperConstraint(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_UPPER
|
inferenceCompatibilityMode -> {
|
||||||
else -> TypeVariableFixationReadiness.READY_FOR_FIXATION_LOWER
|
when {
|
||||||
|
variableHasLowerProperConstraint(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_LOWER
|
||||||
|
else -> TypeVariableFixationReadiness.READY_FOR_FIXATION_UPPER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> TypeVariableFixationReadiness.READY_FOR_FIXATION
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isTypeVariableHasProperConstraint(context: Context, typeVariable: TypeConstructorMarker): Boolean {
|
fun isTypeVariableHasProperConstraint(
|
||||||
|
context: Context,
|
||||||
|
typeVariable: TypeConstructorMarker,
|
||||||
|
inferenceCompatibilityMode: Boolean = false
|
||||||
|
): Boolean {
|
||||||
return with(context) {
|
return with(context) {
|
||||||
val dependencyProvider = TypeVariableDependencyInformationProvider(
|
val dependencyProvider = TypeVariableDependencyInformationProvider(
|
||||||
notFixedTypeVariables, emptyList(), topLevelType = null, context
|
notFixedTypeVariables, emptyList(), topLevelType = null, context
|
||||||
)
|
)
|
||||||
when (getTypeVariableReadiness(typeVariable, dependencyProvider)) {
|
when (getTypeVariableReadiness(typeVariable, dependencyProvider, inferenceCompatibilityMode)) {
|
||||||
TypeVariableFixationReadiness.FORBIDDEN, TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT -> false
|
TypeVariableFixationReadiness.FORBIDDEN, TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
@@ -93,7 +106,8 @@ class VariableFixationFinder(
|
|||||||
allTypeVariables: List<TypeConstructorMarker>,
|
allTypeVariables: List<TypeConstructorMarker>,
|
||||||
postponedArguments: List<PostponedResolvedAtomMarker>,
|
postponedArguments: List<PostponedResolvedAtomMarker>,
|
||||||
completionMode: ConstraintSystemCompletionMode,
|
completionMode: ConstraintSystemCompletionMode,
|
||||||
topLevelType: KotlinTypeMarker
|
topLevelType: KotlinTypeMarker,
|
||||||
|
inferenceCompatibilityMode: Boolean,
|
||||||
): VariableForFixation? {
|
): VariableForFixation? {
|
||||||
if (allTypeVariables.isEmpty()) return null
|
if (allTypeVariables.isEmpty()) return null
|
||||||
|
|
||||||
@@ -101,9 +115,10 @@ class VariableFixationFinder(
|
|||||||
notFixedTypeVariables, postponedArguments, topLevelType.takeIf { completionMode == PARTIAL }, this
|
notFixedTypeVariables, postponedArguments, topLevelType.takeIf { completionMode == PARTIAL }, this
|
||||||
)
|
)
|
||||||
|
|
||||||
val candidate = allTypeVariables.maxByOrNull { getTypeVariableReadiness(it, dependencyProvider) } ?: return null
|
val candidate =
|
||||||
|
allTypeVariables.maxByOrNull { getTypeVariableReadiness(it, dependencyProvider, inferenceCompatibilityMode) } ?: return null
|
||||||
|
|
||||||
return when (getTypeVariableReadiness(candidate, dependencyProvider)) {
|
return when (getTypeVariableReadiness(candidate, dependencyProvider, inferenceCompatibilityMode)) {
|
||||||
TypeVariableFixationReadiness.FORBIDDEN -> null
|
TypeVariableFixationReadiness.FORBIDDEN -> null
|
||||||
TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT -> VariableForFixation(candidate, false)
|
TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT -> VariableForFixation(candidate, false)
|
||||||
TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS ->
|
TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS ->
|
||||||
|
|||||||
+16
-3
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.transformToResolvedLambda
|
import org.jetbrains.kotlin.resolve.calls.components.transformToResolvedLambda
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
@@ -19,6 +21,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|||||||
class KotlinConstraintSystemCompleter(
|
class KotlinConstraintSystemCompleter(
|
||||||
private val resultTypeResolver: ResultTypeResolver,
|
private val resultTypeResolver: ResultTypeResolver,
|
||||||
val variableFixationFinder: VariableFixationFinder,
|
val variableFixationFinder: VariableFixationFinder,
|
||||||
|
val languageVersionSettings: LanguageVersionSettings,
|
||||||
) {
|
) {
|
||||||
private val postponedArgumentInputTypesResolver = PostponedArgumentInputTypesResolver(resultTypeResolver, variableFixationFinder)
|
private val postponedArgumentInputTypesResolver = PostponedArgumentInputTypesResolver(resultTypeResolver, variableFixationFinder)
|
||||||
|
|
||||||
@@ -104,7 +107,8 @@ class KotlinConstraintSystemCompleter(
|
|||||||
postponedArguments,
|
postponedArguments,
|
||||||
topLevelType,
|
topLevelType,
|
||||||
topLevelAtoms,
|
topLevelAtoms,
|
||||||
dependencyProvider
|
dependencyProvider,
|
||||||
|
inferenceCompatibilityMode = isInferenceCompatibilityModeEnabled(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (wasFixedSomeVariable)
|
if (wasFixedSomeVariable)
|
||||||
@@ -257,7 +261,8 @@ class KotlinConstraintSystemCompleter(
|
|||||||
getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms),
|
getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms),
|
||||||
postponedArguments,
|
postponedArguments,
|
||||||
completionMode,
|
completionMode,
|
||||||
topLevelType
|
topLevelType,
|
||||||
|
inferenceCompatibilityMode = isInferenceCompatibilityModeEnabled(),
|
||||||
) ?: break
|
) ?: break
|
||||||
|
|
||||||
if (!variableForFixation.hasProperConstraint && completionMode == ConstraintSystemCompletionMode.PARTIAL)
|
if (!variableForFixation.hasProperConstraint && completionMode == ConstraintSystemCompletionMode.PARTIAL)
|
||||||
@@ -363,9 +368,17 @@ class KotlinConstraintSystemCompleter(
|
|||||||
collectVariablesFromContext: Boolean,
|
collectVariablesFromContext: Boolean,
|
||||||
postponedArguments: List<PostponedResolvedAtom>
|
postponedArguments: List<PostponedResolvedAtom>
|
||||||
) = variableFixationFinder.findFirstVariableForFixation(
|
) = variableFixationFinder.findFirstVariableForFixation(
|
||||||
this, getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms), postponedArguments, completionMode, topLevelType
|
this,
|
||||||
|
getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms),
|
||||||
|
postponedArguments,
|
||||||
|
completionMode,
|
||||||
|
topLevelType,
|
||||||
|
inferenceCompatibilityMode = isInferenceCompatibilityModeEnabled(),
|
||||||
) != null
|
) != null
|
||||||
|
|
||||||
|
private fun isInferenceCompatibilityModeEnabled(): Boolean =
|
||||||
|
languageVersionSettings.supportsFeature(LanguageFeature.InferenceCompatibility)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getOrderedNotAnalyzedPostponedArguments(topLevelAtoms: List<ResolvedAtom>): List<PostponedResolvedAtom> {
|
fun getOrderedNotAnalyzedPostponedArguments(topLevelAtoms: List<ResolvedAtom>): List<PostponedResolvedAtom> {
|
||||||
fun ResolvedAtom.process(to: MutableList<PostponedResolvedAtom>) {
|
fun ResolvedAtom.process(to: MutableList<PostponedResolvedAtom>) {
|
||||||
|
|||||||
+13
-4
@@ -454,13 +454,21 @@ class PostponedArgumentInputTypesResolver(
|
|||||||
postponedArguments: List<PostponedResolvedAtom>,
|
postponedArguments: List<PostponedResolvedAtom>,
|
||||||
topLevelType: UnwrappedType,
|
topLevelType: UnwrappedType,
|
||||||
topLevelAtoms: List<ResolvedAtom>,
|
topLevelAtoms: List<ResolvedAtom>,
|
||||||
dependencyProvider: TypeVariableDependencyInformationProvider
|
dependencyProvider: TypeVariableDependencyInformationProvider,
|
||||||
|
inferenceCompatibilityMode: Boolean = false,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val expectedType = argument.run { safeAs<PostponedAtomWithRevisableExpectedType>()?.revisedExpectedType ?: expectedType }
|
val expectedType = argument.run { safeAs<PostponedAtomWithRevisableExpectedType>()?.revisedExpectedType ?: expectedType }
|
||||||
|
|
||||||
if (expectedType != null && expectedType.isFunctionOrKFunctionTypeWithAnySuspendability) {
|
if (expectedType != null && expectedType.isFunctionOrKFunctionTypeWithAnySuspendability) {
|
||||||
val wasFixedSomeVariable =
|
val wasFixedSomeVariable =
|
||||||
c.fixNextReadyVariableForParameterType(expectedType, postponedArguments, topLevelType, topLevelAtoms, dependencyProvider)
|
c.fixNextReadyVariableForParameterType(
|
||||||
|
expectedType,
|
||||||
|
postponedArguments,
|
||||||
|
topLevelType,
|
||||||
|
topLevelAtoms,
|
||||||
|
dependencyProvider,
|
||||||
|
inferenceCompatibilityMode
|
||||||
|
)
|
||||||
|
|
||||||
if (wasFixedSomeVariable)
|
if (wasFixedSomeVariable)
|
||||||
return true
|
return true
|
||||||
@@ -474,12 +482,13 @@ class PostponedArgumentInputTypesResolver(
|
|||||||
postponedArguments: List<PostponedResolvedAtom>,
|
postponedArguments: List<PostponedResolvedAtom>,
|
||||||
topLevelType: UnwrappedType,
|
topLevelType: UnwrappedType,
|
||||||
topLevelAtoms: List<ResolvedAtom>,
|
topLevelAtoms: List<ResolvedAtom>,
|
||||||
dependencyProvider: TypeVariableDependencyInformationProvider
|
dependencyProvider: TypeVariableDependencyInformationProvider,
|
||||||
|
inferenceCompatibilityMode: Boolean,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val relatedVariables = type.getPureArgumentsForFunctionalTypeOrSubtype()
|
val relatedVariables = type.getPureArgumentsForFunctionalTypeOrSubtype()
|
||||||
.flatMap { getAllDeeplyRelatedTypeVariables(it, dependencyProvider) }
|
.flatMap { getAllDeeplyRelatedTypeVariables(it, dependencyProvider) }
|
||||||
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
|
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
|
||||||
this, relatedVariables, postponedArguments, ConstraintSystemCompletionMode.FULL, topLevelType
|
this, relatedVariables, postponedArguments, ConstraintSystemCompletionMode.FULL, topLevelType, inferenceCompatibilityMode
|
||||||
)
|
)
|
||||||
|
|
||||||
if (variableForFixation == null || !variableForFixation.hasProperConstraint)
|
if (variableForFixation == null || !variableForFixation.hasProperConstraint)
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
// FIR_IDENTICAL
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
|
||||||
// !LANGUAGE: +NewInference
|
// !LANGUAGE: +InferenceCompatibility
|
||||||
|
|
||||||
fun <T, VR : T> foo(x: T, fn: (VR?/*T?*/, T) -> Unit) {}
|
fun <T, VR : T> foo(x: T, fn: (VR?, T) -> Unit) {}
|
||||||
|
|
||||||
fun takeInt(x: Int) {}
|
fun takeInt(x: Int) {}
|
||||||
|
|
||||||
fun main(x: Int) {
|
fun main(x: Int) {
|
||||||
foo(x) { prev: Int?, new -> takeInt(new) } // `new` is `Int` in OI, `Int?` in NI
|
foo(x) { prev: Int?, new -> takeInt(new) } // `new` is `Int` in OI, `Int?` in NI
|
||||||
// It seems, `VR` has been fixed to `Int?` instead of `Int`
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user