[NI] Extract logic about fixation order to separated component

This commit is contained in:
Stanislav Erokhin
2017-07-12 18:42:05 +03:00
parent ff1e230828
commit 3cf240340c
8 changed files with 263 additions and 101 deletions
@@ -19,3 +19,9 @@ package org.jetbrains.kotlin.resolve.calls
val USE_NEW_INFERENCE = false val USE_NEW_INFERENCE = false
val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC = false val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC = false
val USE_CS_COMPLETER_TYPE = CSCompleterType.INITIAL
enum class CSCompleterType {
INITIAL
}
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.resolve.calls.inference.components.FixationOrderCalculator
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.model.PostponedKotlinCallArgument
import org.jetbrains.kotlin.types.UnwrappedType
interface ConstraintSystemCompleter {
enum class CompletionType {
FULL,
PARTIAL
}
interface Context {
val hasContradiction: Boolean
val postponedArguments: List<PostponedKotlinCallArgument>
// type can be proper if it not contains not fixed type variables
fun canBeProper(type: UnwrappedType): Boolean
fun asFixationOrderCalculatorContext(): FixationOrderCalculator.Context
fun asResultTypeResolverContext(): ResultTypeResolver.Context
// mutable operations
fun addError(error: KotlinCallDiagnostic)
fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType)
}
fun runCompletion(
c: Context,
type: CompletionType,
topLevelType: UnwrappedType,
analyze: (PostponedKotlinCallArgument) -> Unit
)
}
@@ -0,0 +1,79 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.resolve.calls.components.ConstraintSystemCompleter.Context
import org.jetbrains.kotlin.resolve.calls.inference.components.FixationOrderCalculator
import org.jetbrains.kotlin.resolve.calls.inference.components.InferenceStepResolver
import org.jetbrains.kotlin.resolve.calls.model.PostponedCallableReferenceArgument
import org.jetbrains.kotlin.resolve.calls.model.PostponedKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.PostponedLambdaArgument
import org.jetbrains.kotlin.types.UnwrappedType
class InitialConstraintSystemCompleterImpl(
private val fixationOrderCalculator: FixationOrderCalculator,
private val inferenceStepResolver: InferenceStepResolver
) : ConstraintSystemCompleter {
override fun runCompletion(
c: Context,
type: ConstraintSystemCompleter.CompletionType,
topLevelType: UnwrappedType,
analyze: (PostponedKotlinCallArgument) -> Unit
) {
if (type == ConstraintSystemCompleter.CompletionType.PARTIAL) return
resolveCallableReferenceArguments(c, analyze)
while (!oneStepToEndOrLambda(c, topLevelType, analyze)) {
// do nothing -- be happy
}
}
private fun resolveCallableReferenceArguments(c: Context, analyze: (PostponedKotlinCallArgument) -> Unit) {
c.postponedArguments.filterIsInstance<PostponedCallableReferenceArgument>().forEach(analyze)
}
// true if it is the end (happy or not)
// every step we fix type variable or analyzeLambda
private fun oneStepToEndOrLambda(
c: Context,
topLevelType: UnwrappedType,
analyze: (PostponedKotlinCallArgument) -> Unit
): Boolean {
val lambda = c.postponedArguments.find { it is PostponedLambdaArgument && canWeAnalyzeIt(c, it) }
if (lambda != null) {
analyze(lambda)
return false
}
val completionOrder = fixationOrderCalculator.computeCompletionOrder(c.asFixationOrderCalculatorContext(), topLevelType)
return inferenceStepResolver.resolveVariables(c, completionOrder)
}
private fun canWeAnalyzeIt(c: Context, lambda: PostponedLambdaArgument): Boolean {
if (lambda.analyzed) return false
if (c.hasContradiction) return true
lambda.receiver?.let {
if (!c.canBeProper(it)) return false
}
return lambda.parameters.all { c.canBeProper(it) }
}
}
@@ -19,11 +19,11 @@ package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.CSCompleterType
import org.jetbrains.kotlin.resolve.calls.inference.components.* import org.jetbrains.kotlin.resolve.calls.USE_CS_COMPLETER_TYPE
import org.jetbrains.kotlin.resolve.calls.components.ConstraintSystemCompleter.CompletionType
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaArgumentConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateCapturedTypes import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateCapturedTypes
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
@@ -32,33 +32,22 @@ import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.NewCapturedType import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.contains
class KotlinCallCompleter( class KotlinCallCompleter(
private val fixationOrderCalculator: FixationOrderCalculator,
private val additionalDiagnosticReporter: AdditionalDiagnosticReporter, private val additionalDiagnosticReporter: AdditionalDiagnosticReporter,
private val inferenceStepResolver: InferenceStepResolver, private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
private val callableReferenceResolver: CallableReferenceResolver initialConstraintSystemCompleter: InitialConstraintSystemCompleterImpl
) { ) {
private val constraintSystemCompleter: ConstraintSystemCompleter = when(USE_CS_COMPLETER_TYPE) {
CSCompleterType.INITIAL -> initialConstraintSystemCompleter
}
interface Context { interface Context {
val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall> val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall>
val hasContradiction: Boolean
fun buildCurrentSubstitutor(): NewTypeSubstitutor
fun buildResultingSubstitutor(): NewTypeSubstitutor fun buildResultingSubstitutor(): NewTypeSubstitutor
val postponedArguments: List<PostponedKotlinCallArgument> val postponedArguments: List<PostponedKotlinCallArgument>
val lambdaArguments: List<PostponedLambdaArgument> val lambdaArguments: List<PostponedLambdaArgument>
// type can be proper if it not contains not fixed type variables
fun canBeProper(type: UnwrappedType): Boolean
fun asFixationOrderCalculatorContext(): FixationOrderCalculator.Context
fun asResultTypeResolverContext(): ResultTypeResolver.Context
// mutable operations
fun asConstraintInjectorContext(): ConstraintInjector.Context
fun addError(error: KotlinCallDiagnostic)
fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType)
fun getBuilder(): ConstraintSystemBuilder
} }
fun transformWhenAmbiguity(candidate: KotlinResolutionCandidate, resolutionCallbacks: KotlinResolutionCallbacks): ResolvedKotlinCall = fun transformWhenAmbiguity(candidate: KotlinResolutionCandidate, resolutionCallbacks: KotlinResolutionCallbacks): ResolvedKotlinCall =
@@ -77,22 +66,18 @@ class KotlinCallCompleter(
else -> candidate as SimpleKotlinResolutionCandidate else -> candidate as SimpleKotlinResolutionCandidate
} }
if (topLevelCall.prepareForCompletion(expectedType)) { val completionType = topLevelCall.prepareForCompletion(expectedType)
val c = candidate.lastCall.constraintSystem.asCallCompleterContext() val constraintSystem = candidate.lastCall.constraintSystem
resolveCallableReferenceArguments(c) constraintSystemCompleter.runCompletion(
constraintSystem.asConstraintSystemCompleterContext(), completionType, candidate.lastCall.descriptorWithFreshTypes.returnTypeOrNothing
topLevelCall.competeCall(c, resolutionCallbacks) ) {
return toCompletedBaseResolvedCall(c, candidate, resolutionCallbacks) postponedArgumentsAnalyzer.analyze(constraintSystem.asPostponedArgumentsAnalyzerContext(), resolutionCallbacks, it)
} }
return ResolvedKotlinCall.OnlyResolvedKotlinCall(candidate) return when (completionType) {
} CompletionType.FULL -> toCompletedBaseResolvedCall(constraintSystem.asCallCompleterContext(), candidate, resolutionCallbacks)
CompletionType.PARTIAL -> ResolvedKotlinCall.OnlyResolvedKotlinCall(candidate)
private fun resolveCallableReferenceArguments(c: Context) {
for (callableReferenceArgument in c.postponedArguments) {
if (callableReferenceArgument !is PostponedCallableReferenceArgument) continue
callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), callableReferenceArgument)
} }
} }
@@ -169,62 +154,17 @@ class KotlinCallCompleter(
} }
// true if we should complete this call // true if we should complete this call
private fun SimpleKotlinResolutionCandidate.prepareForCompletion(expectedType: UnwrappedType?): Boolean { private fun SimpleKotlinResolutionCandidate.prepareForCompletion(expectedType: UnwrappedType?): CompletionType {
val returnType = descriptorWithFreshTypes.returnType?.unwrap() ?: return false val returnType = descriptorWithFreshTypes.returnType?.unwrap() ?: return CompletionType.PARTIAL
if (expectedType != null && !TypeUtils.noExpectedType(expectedType)) { if (expectedType != null && !TypeUtils.noExpectedType(expectedType)) {
csBuilder.addSubtypeConstraint(returnType, expectedType, ExpectedTypeConstraintPosition(kotlinCall)) csBuilder.addSubtypeConstraint(returnType, expectedType, ExpectedTypeConstraintPosition(kotlinCall))
} }
return expectedType != null || csBuilder.isProperType(returnType) return if (expectedType != null || csBuilder.isProperType(returnType)) {
} CompletionType.FULL
private fun SimpleKotlinResolutionCandidate.competeCall(c: Context, resolutionCallbacks: KotlinResolutionCallbacks) {
while (!oneStepToEndOrLambda(c, resolutionCallbacks)) {
// do nothing -- be happy
} }
} else {
CompletionType.PARTIAL
// true if it is the end (happy or not)
// every step we fix type variable or analyzeLambda
private fun SimpleKotlinResolutionCandidate.oneStepToEndOrLambda(c: Context, resolutionCallbacks: KotlinResolutionCallbacks): Boolean {
val lambda = c.lambdaArguments.find { canWeAnalyzeIt(c, it) }
if (lambda != null) {
analyzeLambda(c, resolutionCallbacks, lambda)
return false
} }
val completionOrder = fixationOrderCalculator.computeCompletionOrder(c.asFixationOrderCalculatorContext(), descriptorWithFreshTypes.returnTypeOrNothing)
return inferenceStepResolver.resolveVariables(c, completionOrder)
}
private fun analyzeLambda(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, lambda: PostponedLambdaArgument) {
val currentSubstitutor = c.buildCurrentSubstitutor()
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
val receiver = lambda.receiver?.let(::substitute)
val parameters = lambda.parameters.map(::substitute)
val expectedType = lambda.returnType.takeIf { c.canBeProper(it) }?.let(::substitute)
lambda.analyzed = true
lambda.resultArguments = resolutionCallbacks.analyzeAndGetLambdaResultArguments(lambda.argument, lambda.isSuspend, receiver, parameters, expectedType)
for (resultLambdaArgument in lambda.resultArguments) {
checkSimpleArgument(c.getBuilder(), resultLambdaArgument, lambda.returnType.let(::substitute))
}
if (lambda.resultArguments.isEmpty()) {
val unitType = lambda.returnType.builtIns.unitType
c.getBuilder().addSubtypeConstraint(lambda.returnType.let(::substitute), unitType, LambdaArgumentConstraintPosition(lambda))
}
}
private fun canWeAnalyzeIt(c: Context, lambda: PostponedLambdaArgument): Boolean {
if (lambda.analyzed) return false
if (c.hasContradiction) return true // to record info about lambda and avoid exceptions
lambda.receiver?.let {
if (!c.canBeProper(it)) return false
}
return lambda.parameters.all { c.canBeProper(it) }
} }
} }
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaArgumentConstraintPosition
import org.jetbrains.kotlin.resolve.calls.model.PostponedCallableReferenceArgument
import org.jetbrains.kotlin.resolve.calls.model.PostponedCollectionLiteralArgument
import org.jetbrains.kotlin.resolve.calls.model.PostponedKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.PostponedLambdaArgument
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.typeUtil.builtIns
class PostponedArgumentsAnalyzer(
private val callableReferenceResolver: CallableReferenceResolver
) {
interface Context {
fun buildCurrentSubstitutor(): NewTypeSubstitutor
// type can be proper if it not contains not fixed type variables
fun canBeProper(type: UnwrappedType): Boolean
// mutable operations
fun getBuilder(): ConstraintSystemBuilder
}
fun analyze(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, argument: PostponedKotlinCallArgument) {
when (argument) {
is PostponedLambdaArgument -> analyzeLambda(c, resolutionCallbacks, argument)
is PostponedCallableReferenceArgument -> callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument)
is PostponedCollectionLiteralArgument -> TODO("Not supported")
}
}
private fun analyzeLambda(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, lambda: PostponedLambdaArgument) {
val currentSubstitutor = c.buildCurrentSubstitutor()
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
val receiver = lambda.receiver?.let(::substitute)
val parameters = lambda.parameters.map(::substitute)
val expectedType = lambda.returnType.takeIf { c.canBeProper(it) }?.let(::substitute)
lambda.analyzed = true
lambda.resultArguments = resolutionCallbacks.analyzeAndGetLambdaResultArguments(lambda.argument, lambda.isSuspend, receiver, parameters, expectedType)
for (resultLambdaArgument in lambda.resultArguments) {
checkSimpleArgument(c.getBuilder(), resultLambdaArgument, lambda.returnType.let(::substitute))
}
if (lambda.resultArguments.isEmpty()) {
val unitType = lambda.returnType.builtIns.unitType
c.getBuilder().addSubtypeConstraint(lambda.returnType.let(::substitute), unitType, LambdaArgumentConstraintPosition(lambda))
}
}
}
@@ -16,7 +16,9 @@
package org.jetbrains.kotlin.resolve.calls.inference package org.jetbrains.kotlin.resolve.calls.inference
import org.jetbrains.kotlin.resolve.calls.components.ConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
@@ -28,4 +30,6 @@ interface NewConstraintSystem {
// after this method we shouldn't mutate system via ConstraintSystemBuilder // after this method we shouldn't mutate system via ConstraintSystemBuilder
fun asReadOnlyStorage(): ConstraintStorage fun asReadOnlyStorage(): ConstraintStorage
fun asCallCompleterContext(): KotlinCallCompleter.Context fun asCallCompleterContext(): KotlinCallCompleter.Context
fun asConstraintSystemCompleterContext(): ConstraintSystemCompleter.Context
fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzer.Context
} }
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.resolve.calls.inference.components package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter import org.jetbrains.kotlin.resolve.calls.components.ConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
import org.jetbrains.kotlin.resolve.calls.inference.model.NotEnoughInformationForTypeParameter import org.jetbrains.kotlin.resolve.calls.inference.model.NotEnoughInformationForTypeParameter
@@ -32,7 +32,7 @@ class InferenceStepResolver(
* Resolves one or more of the `variables`. * Resolves one or more of the `variables`.
* Returns `true` if type variable resolution should stop. * Returns `true` if type variable resolution should stop.
*/ */
fun resolveVariables(c: KotlinCallCompleter.Context, variables: List<VariableResolutionNode>): Boolean { fun resolveVariables(c: ConstraintSystemCompleter.Context, variables: List<VariableResolutionNode>): Boolean {
if (variables.isEmpty()) return true if (variables.isEmpty()) return true
if (c.hasContradiction) return true if (c.hasContradiction) return true
@@ -50,7 +50,7 @@ class InferenceStepResolver(
return false return false
} }
private fun VariableWithConstraints.hasProperConstraint(c: KotlinCallCompleter.Context) = private fun VariableWithConstraints.hasProperConstraint(c: ConstraintSystemCompleter.Context) =
constraints.any { !it.isTrivial() && c.canBeProper(it.type) } constraints.any { !it.isTrivial() && c.canBeProper(it.type) }
private fun Constraint.isTrivial() = private fun Constraint.isTrivial() =
@@ -16,7 +16,9 @@
package org.jetbrains.kotlin.resolve.calls.inference.model package org.jetbrains.kotlin.resolve.calls.inference.model
import org.jetbrains.kotlin.resolve.calls.components.ConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.* import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.components.* import org.jetbrains.kotlin.resolve.calls.inference.components.*
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
@@ -34,7 +36,9 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
ConstraintInjector.Context, ConstraintInjector.Context,
ResultTypeResolver.Context, ResultTypeResolver.Context,
KotlinCallCompleter.Context, KotlinCallCompleter.Context,
FixationOrderCalculator.Context FixationOrderCalculator.Context,
ConstraintSystemCompleter.Context,
PostponedArgumentsAnalyzer.Context
{ {
private val storage = MutableConstraintStorage() private val storage = MutableConstraintStorage()
private var state = State.BUILDING private var state = State.BUILDING
@@ -58,8 +62,6 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
override fun getBuilder() = apply { checkState(State.BUILDING, State.COMPLETION) } override fun getBuilder() = apply { checkState(State.BUILDING, State.COMPLETION) }
override fun asConstraintInjectorContext() = apply { checkState(State.BUILDING, State.COMPLETION) }
override fun asReadOnlyStorage(): ConstraintStorage { override fun asReadOnlyStorage(): ConstraintStorage {
checkState(State.BUILDING, State.FREEZED) checkState(State.BUILDING, State.FREEZED)
state = State.FREEZED state = State.FREEZED
@@ -72,6 +74,10 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
return this return this
} }
override fun asConstraintSystemCompleterContext() = apply { checkState(State.BUILDING) }
override fun asPostponedArgumentsAnalyzerContext() = apply { checkState(State.BUILDING) }
// ConstraintSystemOperation // ConstraintSystemOperation
override fun registerVariable(variable: NewTypeVariable) { override fun registerVariable(variable: NewTypeVariable) {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
@@ -178,10 +184,11 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
return storage.buildCurrentSubstitutor() return storage.buildCurrentSubstitutor()
} }
// ConstraintSystemBuilder, KotlinCallCompleter.Context // ConstraintSystemBuilder, ConstraintSystemCompleter.Context
override val hasContradiction: Boolean override val hasContradiction: Boolean
get() = diagnostics.any { !it.candidateApplicability.isSuccess }.apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) } get() = diagnostics.any { !it.candidateApplicability.isSuccess }.apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }
// ConstraintSystemBuilder
override fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall) { override fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall) {
checkState(State.BUILDING, State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
storage.innerCalls.add(innerCall) storage.innerCalls.add(innerCall)
@@ -232,7 +239,7 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
return storage.notFixedTypeVariables return storage.notFixedTypeVariables
} }
// ConstraintInjector.Context, KotlinCallCompleter.Context // ConstraintInjector.Context, ConstraintSystemCompleter.Context
override fun addError(error: KotlinCallDiagnostic) { override fun addError(error: KotlinCallDiagnostic) {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
storage.errors.add(error) storage.errors.add(error)
@@ -240,18 +247,18 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
// KotlinCallCompleter.Context, FixationOrderCalculator.Context // KotlinCallCompleter.Context, FixationOrderCalculator.Context
override val lambdaArguments: List<PostponedLambdaArgument> get() { override val lambdaArguments: List<PostponedLambdaArgument> get() {
checkState(State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
return storage.postponedArguments.filterIsInstance<PostponedLambdaArgument>() return storage.postponedArguments.filterIsInstance<PostponedLambdaArgument>()
} }
// FixationOrderCalculator.Context // FixationOrderCalculator.Context, KotlinCallCompleter.Context, ConstraintSystemCompleter.Context
override val postponedArguments: List<PostponedKotlinCallArgument> override val postponedArguments: List<PostponedKotlinCallArgument>
get() = storage.postponedArguments get() = storage.postponedArguments.apply { checkState(State.BUILDING, State.COMPLETION) }
// KotlinCallCompleter.Context // ConstraintSystemCompleter.Context
override fun asResultTypeResolverContext() = apply { checkState(State.COMPLETION) } override fun asResultTypeResolverContext() = apply { checkState(State.BUILDING, State.COMPLETION) }
override fun asFixationOrderCalculatorContext() = apply { checkState(State.COMPLETION) } override fun asFixationOrderCalculatorContext() = apply { checkState(State.BUILDING, State.COMPLETION) }
override fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType) { override fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType) {
checkState(State.BUILDING, State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
@@ -268,21 +275,25 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
storage.fixedTypeVariables[variable.freshTypeConstructor] = resultType storage.fixedTypeVariables[variable.freshTypeConstructor] = resultType
} }
// KotlinCallCompleter.Context
override val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall> get() { override val innerCalls: List<ResolvedKotlinCall.OnlyResolvedKotlinCall> get() {
checkState(State.COMPLETION) checkState(State.COMPLETION)
return storage.innerCalls return storage.innerCalls
} }
// ConstraintSystemCompleter.Context, PostponedArgumentsAnalyzer.Context
override fun canBeProper(type: UnwrappedType): Boolean { override fun canBeProper(type: UnwrappedType): Boolean {
checkState(State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
return !type.contains { storage.notFixedTypeVariables.containsKey(it.constructor) } return !type.contains { storage.notFixedTypeVariables.containsKey(it.constructor) }
} }
// PostponedArgumentsAnalyzer.Context
override fun buildCurrentSubstitutor(): NewTypeSubstitutor { override fun buildCurrentSubstitutor(): NewTypeSubstitutor {
checkState(State.COMPLETION) checkState(State.BUILDING, State.COMPLETION)
return storage.buildCurrentSubstitutor() return storage.buildCurrentSubstitutor()
} }
// KotlinCallCompleter.Context
override fun buildResultingSubstitutor(): NewTypeSubstitutor { override fun buildResultingSubstitutor(): NewTypeSubstitutor {
checkState(State.COMPLETION) checkState(State.COMPLETION)
val currentSubstitutorMap = storage.fixedTypeVariables.entries.associate { val currentSubstitutorMap = storage.fixedTypeVariables.entries.associate {