[NI] Introduce transactions for constraint system.
This will be used for callable reference resolution.
This commit is contained in:
+1
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
|||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaTypeVariable
|
import org.jetbrains.kotlin.resolve.calls.inference.model.LambdaTypeVariable
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
|
|||||||
+13
-6
@@ -23,21 +23,22 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
|
|
||||||
|
interface ConstraintSystemOperation {
|
||||||
interface ConstraintSystemBuilder {
|
|
||||||
val hasContradiction: Boolean
|
val hasContradiction: Boolean
|
||||||
|
|
||||||
fun registerVariable(variable: NewTypeVariable)
|
fun registerVariable(variable: NewTypeVariable)
|
||||||
|
|
||||||
fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition)
|
fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition)
|
||||||
fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition)
|
fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition)
|
||||||
|
|
||||||
|
fun isProperType(type: UnwrappedType): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
||||||
fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall)
|
fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall)
|
||||||
fun addLambdaArgument(resolvedLambdaArgument: ResolvedLambdaArgument)
|
fun addLambdaArgument(resolvedLambdaArgument: ResolvedLambdaArgument)
|
||||||
|
|
||||||
fun addSubtypeConstraintIfCompatible(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition): Boolean
|
// if runOperations return true, then this operation will be applied, and function return true
|
||||||
|
fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean
|
||||||
fun isProperType(type: UnwrappedType): Boolean
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function removes variables for which we know exact type.
|
* This function removes variables for which we know exact type.
|
||||||
@@ -45,3 +46,9 @@ interface ConstraintSystemBuilder {
|
|||||||
*/
|
*/
|
||||||
fun simplify(): NewTypeSubstitutor
|
fun simplify(): NewTypeSubstitutor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) =
|
||||||
|
runTransaction {
|
||||||
|
if (!hasContradiction) addSubtypeConstraint(lowerType, upperType, position)
|
||||||
|
!hasContradiction
|
||||||
|
}
|
||||||
@@ -57,3 +57,5 @@ fun CallableDescriptor.substituteAndApproximateCapturedTypes(substitutor: NewTyp
|
|||||||
|
|
||||||
return substitute(TypeSubstitutor.create(wrappedSubstitution))
|
return substitute(TypeSubstitutor.create(wrappedSubstitution))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <E> MutableList<E>.trimToSize(newSize: Int) = subList(newSize, size).clear()
|
||||||
+11
-20
@@ -16,12 +16,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.inference.model
|
package org.jetbrains.kotlin.resolve.calls.inference.model
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.trimToSize
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaArgument
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
|
||||||
class MutableVariableWithConstraints(
|
class MutableVariableWithConstraints(
|
||||||
@@ -29,7 +31,7 @@ class MutableVariableWithConstraints(
|
|||||||
constraints: Collection<Constraint> = emptyList()
|
constraints: Collection<Constraint> = emptyList()
|
||||||
) : VariableWithConstraints {
|
) : VariableWithConstraints {
|
||||||
override val constraints: List<Constraint> get() = mutableConstraints
|
override val constraints: List<Constraint> get() = mutableConstraints
|
||||||
private val mutableConstraints = MyArrayList(constraints)
|
private val mutableConstraints = ArrayList(constraints)
|
||||||
|
|
||||||
// return new actual constraint, if this constraint is new
|
// return new actual constraint, if this constraint is new
|
||||||
fun addConstraint(constraint: Constraint): Constraint? {
|
fun addConstraint(constraint: Constraint): Constraint? {
|
||||||
@@ -50,15 +52,15 @@ class MutableVariableWithConstraints(
|
|||||||
return actualConstraint
|
return actualConstraint
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeLastConstraints(shouldRemove: (Constraint) -> Boolean) {
|
// This method should be used only for transaction in constraint system
|
||||||
mutableConstraints.removeLast(shouldRemove)
|
// shouldRemove should give true only for tail elements
|
||||||
|
internal fun removeLastConstraints(shouldRemove: (Constraint) -> Boolean) {
|
||||||
|
mutableConstraints.trimToSize(mutableConstraints.indexOfLast { !shouldRemove(it) } + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo optimize it!
|
// This method should be used only when constraint system has state COMPLETION
|
||||||
fun removeConstrains(shouldRemove: (Constraint) -> Boolean) {
|
internal fun removeConstrains(shouldRemove: (Constraint) -> Boolean) {
|
||||||
val newConstraints = mutableConstraints.filter { !shouldRemove(it) }
|
mutableConstraints.removeAll(shouldRemove)
|
||||||
mutableConstraints.clear()
|
|
||||||
mutableConstraints.addAll(newConstraints)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun newConstraintIsUseless(oldKind: ConstraintKind, newKind: ConstraintKind) =
|
private fun newConstraintIsUseless(oldKind: ConstraintKind, newKind: ConstraintKind) =
|
||||||
@@ -68,24 +70,13 @@ class MutableVariableWithConstraints(
|
|||||||
ConstraintKind.UPPER -> newKind == ConstraintKind.UPPER
|
ConstraintKind.UPPER -> newKind == ConstraintKind.UPPER
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyArrayList<E>(c: Collection<E>): ArrayList<E>(c) {
|
|
||||||
fun removeLast(predicate: (E) -> Boolean) {
|
|
||||||
val newSize = indexOfLast { !predicate(it) } + 1
|
|
||||||
|
|
||||||
if (newSize != size) {
|
|
||||||
removeRange(newSize, size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Constraints for $typeVariable"
|
return "Constraints for $typeVariable"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MutableConstraintStorage : ConstraintStorage {
|
internal class MutableConstraintStorage : ConstraintStorage {
|
||||||
override val allTypeVariables: MutableMap<TypeConstructor, NewTypeVariable> = LinkedHashMap()
|
override val allTypeVariables: MutableMap<TypeConstructor, NewTypeVariable> = LinkedHashMap()
|
||||||
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> = LinkedHashMap()
|
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> = LinkedHashMap()
|
||||||
override val initialConstraints: MutableList<InitialConstraint> = ArrayList()
|
override val initialConstraints: MutableList<InitialConstraint> = ArrayList()
|
||||||
|
|||||||
+55
-26
@@ -17,9 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.resolve.calls.inference.model
|
package org.jetbrains.kotlin.resolve.calls.inference.model
|
||||||
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
|
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
import org.jetbrains.kotlin.resolve.calls.inference.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.buildCurrentSubstitutor
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedKotlinCall
|
||||||
@@ -29,6 +27,7 @@ import org.jetbrains.kotlin.types.ErrorUtils
|
|||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||||
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val resultTypeResolver: ResultTypeResolver):
|
class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val resultTypeResolver: ResultTypeResolver):
|
||||||
@@ -39,11 +38,13 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
|||||||
KotlinCallCompleter.Context,
|
KotlinCallCompleter.Context,
|
||||||
FixationOrderCalculator.Context
|
FixationOrderCalculator.Context
|
||||||
{
|
{
|
||||||
val storage = MutableConstraintStorage()
|
private val storage = MutableConstraintStorage()
|
||||||
private var state = State.BUILDING
|
private var state = State.BUILDING
|
||||||
|
private val typeVariablesTransaction: MutableList<NewTypeVariable> = SmartList()
|
||||||
|
|
||||||
private enum class State {
|
private enum class State {
|
||||||
BUILDING,
|
BUILDING,
|
||||||
|
TRANSACTION,
|
||||||
FREEZED,
|
FREEZED,
|
||||||
COMPLETION
|
COMPLETION
|
||||||
}
|
}
|
||||||
@@ -73,44 +74,72 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConstraintSystemBuilder
|
// ConstraintSystemOperation
|
||||||
override fun registerVariable(variable: NewTypeVariable) {
|
override fun registerVariable(variable: NewTypeVariable) {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||||
|
|
||||||
|
transactionRegisterVariable(variable)
|
||||||
storage.allTypeVariables[variable.freshTypeConstructor] = variable
|
storage.allTypeVariables[variable.freshTypeConstructor] = variable
|
||||||
storage.notFixedTypeVariables[variable.freshTypeConstructor] = MutableVariableWithConstraints(variable)
|
storage.notFixedTypeVariables[variable.freshTypeConstructor] = MutableVariableWithConstraints(variable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) =
|
override fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) =
|
||||||
constraintInjector.addInitialSubtypeConstraint(apply { checkState(State.BUILDING, State.COMPLETION) }, lowerType, upperType, position)
|
constraintInjector.addInitialSubtypeConstraint(apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, lowerType, upperType, position)
|
||||||
|
|
||||||
override fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) =
|
override fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) =
|
||||||
constraintInjector.addInitialEqualityConstraint(apply { checkState(State.BUILDING, State.COMPLETION) }, a, b, position)
|
constraintInjector.addInitialEqualityConstraint(apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }, a, b, position)
|
||||||
|
|
||||||
override fun addLambdaArgument(resolvedLambdaArgument: ResolvedLambdaArgument) {
|
// ConstraintSystemBuilder
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
private fun transactionRegisterVariable(variable: NewTypeVariable) {
|
||||||
storage.lambdaArguments.add(resolvedLambdaArgument)
|
if (state != State.TRANSACTION) return
|
||||||
|
typeVariablesTransaction.add(variable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addSubtypeConstraintIfCompatible(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition): Boolean {
|
private fun closeTransaction(beforeState: State) {
|
||||||
|
checkState(State.TRANSACTION)
|
||||||
|
typeVariablesTransaction.clear()
|
||||||
|
state = beforeState
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION)
|
||||||
|
val beforeState = state
|
||||||
|
val beforeInitialConstraintCount = storage.initialConstraints.size
|
||||||
|
val beforeErrorsCount = storage.errors.size
|
||||||
|
val beforeMaxTypeDepthFromInitialConstraints = storage.maxTypeDepthFromInitialConstraints
|
||||||
|
|
||||||
if (hasContradiction) return false
|
state = State.TRANSACTION
|
||||||
addSubtypeConstraint(lowerType, upperType, position)
|
// typeVariablesTransaction is clear
|
||||||
if (!hasContradiction) return true
|
if (runOperations()) {
|
||||||
|
closeTransaction(beforeState)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
val shouldRemove = { c: Constraint -> c.position === position ||
|
for (addedTypeVariable in typeVariablesTransaction) {
|
||||||
(c.position is IncorporationConstraintPosition && c.position.from === position) }
|
storage.allTypeVariables.remove(addedTypeVariable.freshTypeConstructor)
|
||||||
|
storage.notFixedTypeVariables.remove(addedTypeVariable.freshTypeConstructor)
|
||||||
|
}
|
||||||
|
storage.maxTypeDepthFromInitialConstraints = beforeMaxTypeDepthFromInitialConstraints
|
||||||
|
storage.errors.trimToSize(beforeErrorsCount)
|
||||||
|
|
||||||
|
val addedInitialConstraints = storage.initialConstraints.subList(beforeInitialConstraintCount, storage.initialConstraints.size)
|
||||||
|
|
||||||
|
val shouldRemove = { c: Constraint -> addedInitialConstraints.contains(c.position.initialConstraint) }
|
||||||
|
|
||||||
for (variableWithConstraint in storage.notFixedTypeVariables.values) {
|
for (variableWithConstraint in storage.notFixedTypeVariables.values) {
|
||||||
variableWithConstraint.removeLastConstraints(shouldRemove)
|
variableWithConstraint.removeLastConstraints(shouldRemove)
|
||||||
}
|
}
|
||||||
storage.errors.clear()
|
|
||||||
storage.initialConstraints.removeAt(storage.initialConstraints.lastIndex)
|
|
||||||
|
|
||||||
|
addedInitialConstraints.clear() // remove constraint from storage.initialConstraints
|
||||||
|
closeTransaction(beforeState)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun addLambdaArgument(resolvedLambdaArgument: ResolvedLambdaArgument) {
|
||||||
|
checkState(State.BUILDING, State.COMPLETION)
|
||||||
|
storage.lambdaArguments.add(resolvedLambdaArgument)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getVariablesForFixation(): Map<NewTypeVariable, UnwrappedType> {
|
private fun getVariablesForFixation(): Map<NewTypeVariable, UnwrappedType> {
|
||||||
val fixedVariables = LinkedHashMap<NewTypeVariable, UnwrappedType>()
|
val fixedVariables = LinkedHashMap<NewTypeVariable, UnwrappedType>()
|
||||||
|
|
||||||
@@ -140,7 +169,7 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
|||||||
|
|
||||||
// ConstraintSystemBuilder, KotlinCallCompleter.Context
|
// ConstraintSystemBuilder, KotlinCallCompleter.Context
|
||||||
override val hasContradiction: Boolean
|
override val hasContradiction: Boolean
|
||||||
get() = diagnostics.any { !it.candidateApplicability.isSuccess }.apply { checkState(State.BUILDING, State.COMPLETION) }
|
get() = diagnostics.any { !it.candidateApplicability.isSuccess }.apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }
|
||||||
|
|
||||||
override fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall) {
|
override fun addInnerCall(innerCall: ResolvedKotlinCall.OnlyResolvedKotlinCall) {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION)
|
||||||
@@ -162,7 +191,7 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
|||||||
|
|
||||||
// ResultTypeResolver.Context, ConstraintSystemBuilder
|
// ResultTypeResolver.Context, ConstraintSystemBuilder
|
||||||
override fun isProperType(type: UnwrappedType): Boolean {
|
override fun isProperType(type: UnwrappedType): Boolean {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||||
return !type.contains {
|
return !type.contains {
|
||||||
storage.allTypeVariables.containsKey(it.constructor)
|
storage.allTypeVariables.containsKey(it.constructor)
|
||||||
}
|
}
|
||||||
@@ -170,31 +199,31 @@ class NewConstraintSystemImpl(val constraintInjector: ConstraintInjector, val re
|
|||||||
|
|
||||||
// ConstraintInjector.Context
|
// ConstraintInjector.Context
|
||||||
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> get() {
|
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> get() {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||||
return storage.allTypeVariables
|
return storage.allTypeVariables
|
||||||
}
|
}
|
||||||
|
|
||||||
override var maxTypeDepthFromInitialConstraints: Int
|
override var maxTypeDepthFromInitialConstraints: Int
|
||||||
get() = storage.maxTypeDepthFromInitialConstraints
|
get() = storage.maxTypeDepthFromInitialConstraints
|
||||||
set(value) {
|
set(value) {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||||
storage.maxTypeDepthFromInitialConstraints = value
|
storage.maxTypeDepthFromInitialConstraints = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addInitialConstraint(initialConstraint: InitialConstraint) {
|
override fun addInitialConstraint(initialConstraint: InitialConstraint) {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||||
storage.initialConstraints.add(initialConstraint)
|
storage.initialConstraints.add(initialConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConstraintInjector.Context, FixationOrderCalculator.Context
|
// ConstraintInjector.Context, FixationOrderCalculator.Context
|
||||||
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> get() {
|
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> get() {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||||
return storage.notFixedTypeVariables
|
return storage.notFixedTypeVariables
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConstraintInjector.Context, KotlinCallCompleter.Context
|
// ConstraintInjector.Context, KotlinCallCompleter.Context
|
||||||
override fun addError(error: KotlinCallDiagnostic) {
|
override fun addError(error: KotlinCallDiagnostic) {
|
||||||
checkState(State.BUILDING, State.COMPLETION)
|
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||||
storage.errors.add(error)
|
storage.errors.add(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user