[NI] Introduce inference for coroutines and builder-like constructions
This commit is contained in:
+7
-2
@@ -7,9 +7,12 @@ package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.types.NonFixedType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
// stateless component
|
||||
@@ -22,6 +25,7 @@ interface KotlinResolutionStatelessCallbacks {
|
||||
fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean
|
||||
fun getScopeTowerForCallableReferenceArgument(argument: CallableReferenceKotlinCallArgument): ImplicitScopeTower
|
||||
fun getVariableCandidateIfInvoke(functionCall: KotlinCall): KotlinResolutionCandidate?
|
||||
fun isCoroutineCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean
|
||||
}
|
||||
|
||||
// This components hold state (trace). Work with this carefully.
|
||||
@@ -31,8 +35,9 @@ interface KotlinResolutionCallbacks {
|
||||
isSuspend: Boolean,
|
||||
receiverType: UnwrappedType?,
|
||||
parameters: List<UnwrappedType>,
|
||||
expectedReturnType: UnwrappedType? // null means, that return type is not proper i.e. it depends on some type variables
|
||||
): List<KotlinCallArgument>
|
||||
expectedReturnType: UnwrappedType?, // null means, that return type is not proper i.e. it depends on some type variables
|
||||
stubsForPostponedVariables: Map<NewTypeVariable, NonFixedType>
|
||||
): Pair<List<KotlinCallArgument>, InferenceSession?>
|
||||
|
||||
fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom)
|
||||
|
||||
|
||||
+12
@@ -6,9 +6,13 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.model.CallResolutionResult
|
||||
import org.jetbrains.kotlin.resolve.calls.model.CompletedCallResolutionResult
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PartialCallResolutionResult
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
interface InferenceSession {
|
||||
companion object {
|
||||
@@ -16,20 +20,28 @@ interface InferenceSession {
|
||||
override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean = true
|
||||
override fun addPartialCallInfo(callInfo: PartialCallInfo) {}
|
||||
override fun addErrorCallInfo(callInfo: ErrorCallInfo) {}
|
||||
override fun addCompletedCallInfo(callInfo: CompletedCallInfo) {}
|
||||
override fun currentConstraintSystem(): ConstraintStorage = ConstraintStorage.Empty
|
||||
override fun inferPostponedVariables(initialStorage: ConstraintStorage): Map<TypeConstructor, UnwrappedType> = emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean
|
||||
fun addPartialCallInfo(callInfo: PartialCallInfo)
|
||||
fun addCompletedCallInfo(callInfo: CompletedCallInfo)
|
||||
fun addErrorCallInfo(callInfo: ErrorCallInfo)
|
||||
fun currentConstraintSystem(): ConstraintStorage
|
||||
fun inferPostponedVariables(initialStorage: ConstraintStorage): Map<TypeConstructor, UnwrappedType>
|
||||
}
|
||||
|
||||
interface PartialCallInfo {
|
||||
val callResolutionResult: PartialCallResolutionResult
|
||||
}
|
||||
|
||||
interface CompletedCallInfo {
|
||||
val callResolutionResult: CompletedCallResolutionResult
|
||||
}
|
||||
|
||||
interface ErrorCallInfo {
|
||||
val callResolutionResult: CallResolutionResult
|
||||
}
|
||||
+28
-7
@@ -8,9 +8,10 @@ package org.jetbrains.kotlin.resolve.calls.components
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.addSubsystemFromArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.NonFixedType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
|
||||
@@ -18,7 +19,8 @@ class PostponedArgumentsAnalyzer(
|
||||
private val callableReferenceResolver: CallableReferenceResolver
|
||||
) {
|
||||
interface Context {
|
||||
fun buildCurrentSubstitutor(): NewTypeSubstitutor
|
||||
fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, NonFixedType>): NewTypeSubstitutor
|
||||
fun bindingStubsForPostponedVariables(): Map<NewTypeVariable, NonFixedType>
|
||||
|
||||
// type can be proper if it not contains not fixed type variables
|
||||
fun canBeProper(type: UnwrappedType): Boolean
|
||||
@@ -42,7 +44,9 @@ class PostponedArgumentsAnalyzer(
|
||||
analyzeLambda(c, resolutionCallbacks, argument, diagnosticsHolder)
|
||||
|
||||
is LambdaWithTypeVariableAsExpectedTypeAtom ->
|
||||
analyzeLambda(c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder)
|
||||
analyzeLambda(
|
||||
c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder
|
||||
)
|
||||
|
||||
is ResolvedCallableReferenceAtom ->
|
||||
callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument, diagnosticsHolder)
|
||||
@@ -59,7 +63,9 @@ class PostponedArgumentsAnalyzer(
|
||||
lambda: ResolvedLambdaAtom,
|
||||
diagnosticHolder: KotlinDiagnosticsHolder
|
||||
) {
|
||||
val currentSubstitutor = c.buildCurrentSubstitutor()
|
||||
val stubsForPostponedVariables = c.bindingStubsForPostponedVariables()
|
||||
val currentSubstitutor = c.buildCurrentSubstitutor(stubsForPostponedVariables.mapKeys { it.key.freshTypeConstructor })
|
||||
|
||||
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
|
||||
|
||||
val receiver = lambda.receiver?.let(::substitute)
|
||||
@@ -75,12 +81,13 @@ class PostponedArgumentsAnalyzer(
|
||||
else -> null
|
||||
}
|
||||
|
||||
val returnArguments = resolutionCallbacks.analyzeAndGetLambdaReturnArguments(
|
||||
val (returnArguments, inferenceSession) = resolutionCallbacks.analyzeAndGetLambdaReturnArguments(
|
||||
lambda.atom,
|
||||
lambda.isSuspend,
|
||||
receiver,
|
||||
parameters,
|
||||
expectedTypeForReturnArguments
|
||||
expectedTypeForReturnArguments,
|
||||
stubsForPostponedVariables
|
||||
)
|
||||
|
||||
returnArguments.forEach { c.addSubsystemFromArgument(it) }
|
||||
@@ -94,6 +101,20 @@ class PostponedArgumentsAnalyzer(
|
||||
c.getBuilder().addSubtypeConstraint(lambda.returnType.let(::substitute), unitType, LambdaArgumentConstraintPosition(lambda))
|
||||
}
|
||||
|
||||
if (inferenceSession != null) {
|
||||
val storageSnapshot = c.getBuilder().copyCurrentStorage()
|
||||
|
||||
val postponedVariables = inferenceSession.inferPostponedVariables(storageSnapshot)
|
||||
|
||||
for ((constructor, resultType) in postponedVariables) {
|
||||
val variableWithConstraints = storageSnapshot.notFixedTypeVariables[constructor] ?: continue
|
||||
val variable = variableWithConstraints.typeVariable
|
||||
|
||||
c.getBuilder().unmarkPostponedVariable(variable)
|
||||
c.getBuilder().addEqualityConstraint(variable.defaultType, resultType, CoroutinePosition())
|
||||
}
|
||||
}
|
||||
|
||||
lambda.setAnalyzedResults(returnArguments, subResolvedKtPrimitives)
|
||||
}
|
||||
}
|
||||
+16
-4
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ExplicitTypeParameterConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.KnownTypeParameterConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
|
||||
@@ -21,6 +18,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.InfixCallNoInfixModifier
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorModifier
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal object CheckInstantiationOfAbstractClass : ResolutionPart() {
|
||||
@@ -194,6 +192,20 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
|
||||
}
|
||||
}
|
||||
|
||||
internal object InferLaterInitializerResolutionPart : ResolutionPart() {
|
||||
override fun KotlinResolutionCandidate.process(workIndex: Int) {
|
||||
resolvedCall.argumentToCandidateParameter
|
||||
.filter { (argument, parameter) -> callComponents.statelessCallbacks.isCoroutineCall(argument, parameter) }
|
||||
.flatMap { (_, parameter) ->
|
||||
resolvedCall.substitutor.freshVariables.filter { variable ->
|
||||
parameter.type.contains { it.constructor == variable.originalTypeParameter.typeConstructor }
|
||||
}
|
||||
}
|
||||
.distinct()
|
||||
.forEach { csBuilder.markPostponedVariable(it) }
|
||||
}
|
||||
}
|
||||
|
||||
internal object CheckExplicitReceiverKindConsistency : ResolutionPart() {
|
||||
private fun KotlinResolutionCandidate.hasError(): Nothing =
|
||||
error(
|
||||
|
||||
+5
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
@@ -29,6 +30,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
interface ConstraintSystemOperation {
|
||||
val hasContradiction: Boolean
|
||||
fun registerVariable(variable: NewTypeVariable)
|
||||
fun markPostponedVariable(variable: NewTypeVariable)
|
||||
fun unmarkPostponedVariable(variable: NewTypeVariable)
|
||||
|
||||
fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition)
|
||||
fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition)
|
||||
@@ -45,6 +48,8 @@ interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
||||
fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean
|
||||
|
||||
fun buildCurrentSubstitutor(): NewTypeSubstitutor
|
||||
|
||||
fun copyCurrentStorage(): ConstraintStorage
|
||||
}
|
||||
|
||||
fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(
|
||||
|
||||
+3
-4
@@ -20,13 +20,12 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
fun ConstraintStorage.buildCurrentSubstitutor() = NewTypeSubstitutorByConstructorMap(fixedTypeVariables.entries.associate {
|
||||
it.key to it.value
|
||||
})
|
||||
fun ConstraintStorage.buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, NonFixedType>): NewTypeSubstitutorByConstructorMap =
|
||||
NewTypeSubstitutorByConstructorMap(fixedTypeVariables.entries.associate { it.key to it.value } + additionalBindings)
|
||||
|
||||
fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor {
|
||||
val currentSubstitutorMap = fixedTypeVariables.entries.associate {
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
|
||||
var maxTypeDepthFromInitialConstraints: Int
|
||||
val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints>
|
||||
val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType>
|
||||
|
||||
fun addInitialConstraint(initialConstraint: InitialConstraint)
|
||||
fun addError(error: KotlinCallDiagnostic)
|
||||
|
||||
+41
-4
@@ -27,9 +27,13 @@ class KotlinConstraintSystemCompleter(
|
||||
interface Context : VariableFixationFinder.Context, ResultTypeResolver.Context {
|
||||
override val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>
|
||||
|
||||
override val postponedTypeVariables: List<NewTypeVariable>
|
||||
|
||||
// type can be proper if it not contains not fixed type variables
|
||||
fun canBeProper(type: UnwrappedType): Boolean
|
||||
|
||||
fun containsOnlyFixedOrPostponedVariables(type: UnwrappedType): Boolean
|
||||
|
||||
// mutable operations
|
||||
fun addError(error: KotlinCallDiagnostic)
|
||||
|
||||
@@ -42,11 +46,28 @@ class KotlinConstraintSystemCompleter(
|
||||
topLevelAtoms: List<ResolvedAtom>,
|
||||
topLevelType: UnwrappedType,
|
||||
analyze: (PostponedResolvedAtom) -> Unit
|
||||
) {
|
||||
runCompletion(c, completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext = false, analyze = analyze)
|
||||
}
|
||||
|
||||
fun completeConstraintSystem(c: Context, topLevelType: UnwrappedType) {
|
||||
runCompletion(c, ConstraintSystemCompletionMode.FULL, emptyList(), topLevelType, collectVariablesFromContext = true) {
|
||||
error("Shouldn't be called in complete constraint system mode")
|
||||
}
|
||||
}
|
||||
|
||||
private fun runCompletion(
|
||||
c: Context,
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
topLevelAtoms: List<ResolvedAtom>,
|
||||
topLevelType: UnwrappedType,
|
||||
collectVariablesFromContext: Boolean,
|
||||
analyze: (PostponedResolvedAtom) -> Unit
|
||||
) {
|
||||
while (true) {
|
||||
if (analyzePostponeArgumentIfPossible(c, topLevelAtoms, analyze)) continue
|
||||
|
||||
val allTypeVariables = getOrderedAllTypeVariables(c, topLevelAtoms)
|
||||
val allTypeVariables = getOrderedAllTypeVariables(c, collectVariablesFromContext, topLevelAtoms)
|
||||
val postponedKtPrimitives = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
|
||||
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
|
||||
c, allTypeVariables, postponedKtPrimitives, completionMode, topLevelType
|
||||
@@ -75,6 +96,10 @@ class KotlinConstraintSystemCompleter(
|
||||
if (completionMode == ConstraintSystemCompletionMode.FULL) {
|
||||
// force resolution for all not-analyzed argument's
|
||||
getOrderedNotAnalyzedPostponedArguments(topLevelAtoms).forEach(analyze)
|
||||
|
||||
if (c.notFixedTypeVariables.isNotEmpty() && c.postponedTypeVariables.isEmpty()) {
|
||||
runCompletion(c, completionMode, topLevelAtoms, topLevelType, analyze)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +155,13 @@ class KotlinConstraintSystemCompleter(
|
||||
return notAnalyzedArguments
|
||||
}
|
||||
|
||||
private fun getOrderedAllTypeVariables(c: Context, topLevelAtoms: List<ResolvedAtom>): List<TypeConstructor> {
|
||||
private fun getOrderedAllTypeVariables(
|
||||
c: Context,
|
||||
collectVariablesFromContext: Boolean,
|
||||
topLevelAtoms: List<ResolvedAtom>
|
||||
): List<TypeConstructor> {
|
||||
if (collectVariablesFromContext) return c.notFixedTypeVariables.keys.toList()
|
||||
|
||||
fun ResolvedAtom.process(to: LinkedHashSet<TypeConstructor>) {
|
||||
val typeVariables = when (this) {
|
||||
is ResolvedCallAtom -> substitutor.freshVariables
|
||||
@@ -166,7 +197,7 @@ class KotlinConstraintSystemCompleter(
|
||||
private fun canWeAnalyzeIt(c: Context, argument: PostponedResolvedAtom): Boolean {
|
||||
if (argument.analyzed) return false
|
||||
|
||||
return argument.inputTypes.all { c.canBeProper(it) }
|
||||
return argument.inputTypes.all { c.containsOnlyFixedOrPostponedVariables(it) }
|
||||
}
|
||||
|
||||
private fun fixVariable(
|
||||
@@ -176,9 +207,15 @@ class KotlinConstraintSystemCompleter(
|
||||
postponedResolveKtPrimitives: List<PostponedResolvedAtom>
|
||||
) {
|
||||
val direction = TypeVariableDirectionCalculator(c, postponedResolveKtPrimitives, topLevelType).getDirection(variableWithConstraints)
|
||||
fixVariable(c, variableWithConstraints, direction)
|
||||
}
|
||||
|
||||
fun fixVariable(
|
||||
c: Context,
|
||||
variableWithConstraints: VariableWithConstraints,
|
||||
direction: TypeVariableDirectionCalculator.ResolveDirection
|
||||
) {
|
||||
val resultType = resultTypeResolver.findResultType(c, variableWithConstraints, direction)
|
||||
|
||||
c.fixVariable(variableWithConstraints.typeVariable, resultType)
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintS
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
class VariableFixationFinder {
|
||||
interface Context {
|
||||
val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>
|
||||
val postponedTypeVariables: List<NewTypeVariable>
|
||||
}
|
||||
|
||||
data class VariableForFixation(val variable: TypeConstructor, val hasProperConstraint: Boolean)
|
||||
@@ -67,10 +69,12 @@ class VariableFixationFinder {
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
topLevelType: UnwrappedType
|
||||
): VariableForFixation? {
|
||||
val dependencyProvider = TypeVariableDependencyInformationProvider(notFixedTypeVariables, postponedKtPrimitives,
|
||||
topLevelType.takeIf { completionMode == PARTIAL })
|
||||
val dependencyProvider = TypeVariableDependencyInformationProvider(
|
||||
notFixedTypeVariables, postponedKtPrimitives, topLevelType.takeIf { completionMode == PARTIAL }
|
||||
)
|
||||
|
||||
val candidate = allTypeVariables.maxBy { getTypeVariableReadiness(it, dependencyProvider) } ?: return null
|
||||
|
||||
val candidateReadiness = getTypeVariableReadiness(candidate, dependencyProvider)
|
||||
return when (candidateReadiness) {
|
||||
TypeVariableFixationReadiness.FORBIDDEN -> null
|
||||
|
||||
+4
@@ -69,6 +69,10 @@ class IncorporationConstraintPosition(val from: ConstraintPosition, val initialC
|
||||
override fun toString() = "Incorporate $initialConstraint from position $from"
|
||||
}
|
||||
|
||||
class CoroutinePosition() : ConstraintPosition() {
|
||||
override fun toString(): String = "for coroutine call"
|
||||
}
|
||||
|
||||
@Deprecated("Should be used only in SimpleConstraintSystemImpl")
|
||||
object SimpleConstraintSystemConstraintPosition : ConstraintPosition()
|
||||
|
||||
|
||||
+3
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.model
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
@@ -42,6 +43,7 @@ interface ConstraintStorage {
|
||||
val errors: List<KotlinCallDiagnostic>
|
||||
val hasContradiction: Boolean
|
||||
val fixedTypeVariables: Map<TypeConstructor, UnwrappedType>
|
||||
val postponedTypeVariables: List<NewTypeVariable>
|
||||
|
||||
object Empty : ConstraintStorage {
|
||||
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> get() = emptyMap()
|
||||
@@ -51,6 +53,7 @@ interface ConstraintStorage {
|
||||
override val errors: List<KotlinCallDiagnostic> get() = emptyList()
|
||||
override val hasContradiction: Boolean get() = false
|
||||
override val fixedTypeVariables: Map<TypeConstructor, UnwrappedType> get() = emptyMap()
|
||||
override val postponedTypeVariables: List<NewTypeVariable> get() = emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
-2
@@ -5,13 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.model
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.trimToSize
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.LinkedHashMap
|
||||
|
||||
|
||||
class MutableVariableWithConstraints(
|
||||
@@ -25,6 +26,7 @@ class MutableVariableWithConstraints(
|
||||
}
|
||||
return simplifiedConstraints!!
|
||||
}
|
||||
|
||||
private val mutableConstraints = ArrayList(constraints)
|
||||
|
||||
private var simplifiedConstraints: List<Constraint>? = null
|
||||
@@ -94,4 +96,33 @@ internal class MutableConstraintStorage : ConstraintStorage {
|
||||
override val errors: MutableList<KotlinCallDiagnostic> = ArrayList()
|
||||
override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess }
|
||||
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType> = LinkedHashMap()
|
||||
}
|
||||
override val postponedTypeVariables: ArrayList<NewTypeVariable> = ArrayList()
|
||||
|
||||
fun copy(): ConstraintStorage {
|
||||
return object : ConstraintStorage {
|
||||
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> =
|
||||
this@MutableConstraintStorage.allTypeVariables.toMap()
|
||||
|
||||
override val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints> =
|
||||
this@MutableConstraintStorage.notFixedTypeVariables.toMap()
|
||||
|
||||
override val initialConstraints: List<InitialConstraint> =
|
||||
this@MutableConstraintStorage.initialConstraints.toList()
|
||||
|
||||
override val maxTypeDepthFromInitialConstraints: Int =
|
||||
this@MutableConstraintStorage.maxTypeDepthFromInitialConstraints
|
||||
|
||||
override val errors: List<KotlinCallDiagnostic> =
|
||||
this@MutableConstraintStorage.errors.toList()
|
||||
|
||||
override val hasContradiction: Boolean =
|
||||
this@MutableConstraintStorage.hasContradiction
|
||||
|
||||
override val fixedTypeVariables: Map<TypeConstructor, UnwrappedType> =
|
||||
this@MutableConstraintStorage.fixedTypeVariables.toMap()
|
||||
|
||||
override val postponedTypeVariables: List<NewTypeVariable> =
|
||||
this@MutableConstraintStorage.postponedTypeVariables.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+46
-1
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintS
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.types.NonFixedType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
@@ -70,6 +71,14 @@ class NewConstraintSystemImpl(
|
||||
storage.notFixedTypeVariables[variable.freshTypeConstructor] = MutableVariableWithConstraints(variable)
|
||||
}
|
||||
|
||||
override fun markPostponedVariable(variable: NewTypeVariable) {
|
||||
storage.postponedTypeVariables += variable
|
||||
}
|
||||
|
||||
override fun unmarkPostponedVariable(variable: NewTypeVariable) {
|
||||
storage.postponedTypeVariables -= variable
|
||||
}
|
||||
|
||||
override fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) =
|
||||
constraintInjector.addInitialSubtypeConstraint(
|
||||
apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) },
|
||||
@@ -163,6 +172,7 @@ class NewConstraintSystemImpl(
|
||||
Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints)
|
||||
storage.errors.addAll(otherSystem.errors)
|
||||
storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables)
|
||||
storage.postponedTypeVariables.addAll(otherSystem.postponedTypeVariables)
|
||||
}
|
||||
|
||||
// ResultTypeResolver.Context, ConstraintSystemBuilder
|
||||
@@ -204,6 +214,18 @@ class NewConstraintSystemImpl(
|
||||
return storage.notFixedTypeVariables
|
||||
}
|
||||
|
||||
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType>
|
||||
get() {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return storage.fixedTypeVariables
|
||||
}
|
||||
|
||||
override val postponedTypeVariables: List<NewTypeVariable>
|
||||
get() {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return storage.postponedTypeVariables
|
||||
}
|
||||
|
||||
// ConstraintInjector.Context, KotlinConstraintSystemCompleter.Context
|
||||
override fun addError(error: KotlinCallDiagnostic) {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
@@ -232,10 +254,33 @@ class NewConstraintSystemImpl(
|
||||
return !type.contains { storage.notFixedTypeVariables.containsKey(it.constructor) }
|
||||
}
|
||||
|
||||
override fun containsOnlyFixedOrPostponedVariables(type: UnwrappedType): Boolean {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return !type.contains {
|
||||
val variable = storage.notFixedTypeVariables[it.constructor]?.typeVariable
|
||||
variable !in storage.postponedTypeVariables && storage.notFixedTypeVariables.containsKey(it.constructor)
|
||||
}
|
||||
}
|
||||
|
||||
// PostponedArgumentsAnalyzer.Context
|
||||
override fun buildCurrentSubstitutor(): NewTypeSubstitutor {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return storage.buildCurrentSubstitutor()
|
||||
return buildCurrentSubstitutor(emptyMap())
|
||||
}
|
||||
|
||||
override fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, NonFixedType>): NewTypeSubstitutor {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return storage.buildCurrentSubstitutor(additionalBindings)
|
||||
}
|
||||
|
||||
override fun bindingStubsForPostponedVariables(): Map<NewTypeVariable, NonFixedType> {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return storage.postponedTypeVariables.associate { it to NonFixedType(it.freshTypeConstructor) }
|
||||
}
|
||||
|
||||
override fun copyCurrentStorage(): ConstraintStorage {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return storage.copy()
|
||||
}
|
||||
|
||||
// PostponedArgumentsAnalyzer.Context
|
||||
|
||||
+4
-2
@@ -191,7 +191,8 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
|
||||
NoArguments,
|
||||
CreateFreshVariablesSubstitutor,
|
||||
CheckExplicitReceiverKindConsistency,
|
||||
CheckReceivers
|
||||
CheckReceivers,
|
||||
InferLaterInitializerResolutionPart
|
||||
),
|
||||
FUNCTION(
|
||||
CheckInstantiationOfAbstractClass,
|
||||
@@ -205,7 +206,8 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
|
||||
CheckExplicitReceiverKindConsistency,
|
||||
CheckReceivers,
|
||||
CheckArguments,
|
||||
CheckExternalArgument
|
||||
CheckExternalArgument,
|
||||
InferLaterInitializerResolutionPart
|
||||
),
|
||||
INVOKE(*FUNCTION.resolutionSequence.toTypedArray()),
|
||||
UNSUPPORTED();
|
||||
|
||||
+1
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
Reference in New Issue
Block a user