Add more methods to interface ConstraintSystem
To minimize usages of ConstraintSystemImpl
This commit is contained in:
@@ -207,7 +207,7 @@ public object Renderers {
|
|||||||
public fun renderParameterConstraintError(
|
public fun renderParameterConstraintError(
|
||||||
inferenceErrorData: InferenceErrorData, renderer: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, renderer: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
val constraintErrors = (inferenceErrorData.constraintSystem as ConstraintSystemImpl).constraintErrors
|
val constraintErrors = inferenceErrorData.constraintSystem.getStatus().constraintErrors
|
||||||
val errorPositions = constraintErrors.filter { it is ParameterConstraintError }.map { it.constraintPosition }
|
val errorPositions = constraintErrors.filter { it is ParameterConstraintError }.map { it.constraintPosition }
|
||||||
return renderer.table(
|
return renderer.table(
|
||||||
TabledDescriptorRenderer
|
TabledDescriptorRenderer
|
||||||
@@ -308,8 +308,8 @@ public object Renderers {
|
|||||||
public fun renderCannotCaptureTypeParameterError(
|
public fun renderCannotCaptureTypeParameterError(
|
||||||
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
val constraintSystem = inferenceErrorData.constraintSystem as ConstraintSystemImpl
|
val constraintSystem = inferenceErrorData.constraintSystem
|
||||||
val errors = constraintSystem.constraintErrors
|
val errors = constraintSystem.getStatus().constraintErrors
|
||||||
val typeParameterWithCapturedConstraint = (errors.firstOrNull { it is CannotCapture } as? CannotCapture)?.typeVariable
|
val typeParameterWithCapturedConstraint = (errors.firstOrNull { it is CannotCapture } as? CannotCapture)?.typeVariable
|
||||||
if (typeParameterWithCapturedConstraint == null) {
|
if (typeParameterWithCapturedConstraint == null) {
|
||||||
LOG.error(renderDebugMessage("An error 'cannot capture type parameter' is not found in errors", inferenceErrorData))
|
LOG.error(renderDebugMessage("An error 'cannot capture type parameter' is not found in errors", inferenceErrorData))
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
|||||||
import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.filterConstraintsOut
|
import org.jetbrains.kotlin.resolve.calls.inference.filterConstraintsOut
|
||||||
@@ -149,7 +148,7 @@ public class CallCompleter(
|
|||||||
|
|
||||||
val returnType = getCandidateDescriptor().getReturnType()
|
val returnType = getCandidateDescriptor().getReturnType()
|
||||||
if (returnType != null) {
|
if (returnType != null) {
|
||||||
getConstraintSystem()!!.addSupertypeConstraint(expectedType, returnType, EXPECTED_TYPE_POSITION.position())
|
constraintSystem!!.addSupertypeConstraint(expectedType, returnType, EXPECTED_TYPE_POSITION.position())
|
||||||
}
|
}
|
||||||
|
|
||||||
val constraintSystemCompleter = trace[CONSTRAINT_SYSTEM_COMPLETER, getCall().getCalleeExpression()]
|
val constraintSystemCompleter = trace[CONSTRAINT_SYSTEM_COMPLETER, getCall().getCalleeExpression()]
|
||||||
@@ -172,10 +171,9 @@ public class CallCompleter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val constraintSystem = getConstraintSystem() as ConstraintSystemImpl
|
constraintSystem!!.fixVariables()
|
||||||
constraintSystem.fixVariables()
|
|
||||||
|
|
||||||
setResultingSubstitutor(getConstraintSystem()!!.getResultingSubstitutor())
|
setResultingSubstitutor(constraintSystem!!.getResultingSubstitutor())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableDescriptor> MutableResolvedCall<D>.updateResolutionStatusFromConstraintSystem(
|
private fun <D : CallableDescriptor> MutableResolvedCall<D>.updateResolutionStatusFromConstraintSystem(
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
@@ -70,11 +69,8 @@ private fun getReturnTypeForCallable(type: KotlinType) =
|
|||||||
type.getArguments().last().getType()
|
type.getArguments().last().getType()
|
||||||
|
|
||||||
private fun CallableDescriptor.hasReturnTypeDependentOnUninferredParams(constraintSystem: ConstraintSystem): Boolean {
|
private fun CallableDescriptor.hasReturnTypeDependentOnUninferredParams(constraintSystem: ConstraintSystem): Boolean {
|
||||||
val returnType = getReturnType() ?: return false
|
val returnType = returnType ?: return false
|
||||||
|
val nestedTypeVariables = constraintSystem.getNestedTypeVariables(returnType, original = true)
|
||||||
val nestedTypeVariables = with (constraintSystem as ConstraintSystemImpl) {
|
|
||||||
returnType.getNestedTypeVariables()
|
|
||||||
}
|
|
||||||
return nestedTypeVariables.any { constraintSystem.getTypeBounds(it).value == null }
|
return nestedTypeVariables.any { constraintSystem.getTypeBounds(it).value == null }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -148,14 +148,13 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
|||||||
val resultingCall = resolutionResults.resultingCall
|
val resultingCall = resolutionResults.resultingCall
|
||||||
if (resultingCall.isCompleted) return false
|
if (resultingCall.isCompleted) return false
|
||||||
|
|
||||||
val argumentConstraintSystem = resultingCall.constraintSystem as ConstraintSystemImpl? ?: return false
|
val argumentConstraintSystem = resultingCall.constraintSystem ?: return false
|
||||||
|
|
||||||
val candidateDescriptor = resultingCall.candidateDescriptor
|
val candidateDescriptor = resultingCall.candidateDescriptor
|
||||||
val returnType = candidateDescriptor.returnType ?: return false
|
val returnType = candidateDescriptor.returnType ?: return false
|
||||||
|
|
||||||
val nestedTypeVariables = with (argumentConstraintSystem) {
|
val nestedTypeVariables = argumentConstraintSystem.getNestedTypeVariables(returnType, original = true)
|
||||||
returnType.getNestedTypeVariables()
|
|
||||||
}
|
|
||||||
// we add an additional type variable only if no information is inferred for it.
|
// we add an additional type variable only if no information is inferred for it.
|
||||||
// otherwise we add currently inferred return type as before
|
// otherwise we add currently inferred return type as before
|
||||||
if (nestedTypeVariables.any { argumentConstraintSystem.getTypeBounds(it).bounds.isNotEmpty() }) return false
|
if (nestedTypeVariables.any { argumentConstraintSystem.getTypeBounds(it).bounds.isNotEmpty() }) return false
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ public interface ConstraintSystem {
|
|||||||
public fun getPartialSubstitutor(): TypeSubstitutor
|
public fun getPartialSubstitutor(): TypeSubstitutor
|
||||||
|
|
||||||
public fun copy(filterConstraintPosition: (ConstraintPosition) -> Boolean = { true }): ConstraintSystem
|
public fun copy(filterConstraintPosition: (ConstraintPosition) -> Boolean = { true }): ConstraintSystem
|
||||||
|
|
||||||
|
public fun fixVariables()
|
||||||
|
|
||||||
|
public fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
|
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
|
||||||
|
|||||||
+10
-9
@@ -63,8 +63,6 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
private val usedInBounds = HashMap<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>()
|
private val usedInBounds = HashMap<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>()
|
||||||
|
|
||||||
private val errors = ArrayList<ConstraintError>()
|
private val errors = ArrayList<ConstraintError>()
|
||||||
public val constraintErrors: List<ConstraintError>
|
|
||||||
get() = errors
|
|
||||||
|
|
||||||
private val initialConstraints = ArrayList<Constraint>()
|
private val initialConstraints = ArrayList<Constraint>()
|
||||||
|
|
||||||
@@ -106,6 +104,9 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
|
|
||||||
override fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError() =
|
override fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError() =
|
||||||
localTypeParameterBounds.values.any { it.typeVariable.hasOnlyInputTypesAnnotation() && it.value == null }
|
localTypeParameterBounds.values.any { it.typeVariable.hasOnlyInputTypesAnnotation() && it.value == null }
|
||||||
|
|
||||||
|
override val constraintErrors: List<ConstraintError>
|
||||||
|
get() = errors
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getParameterToInferredValueMap(
|
private fun getParameterToInferredValueMap(
|
||||||
@@ -171,10 +172,10 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
type -> type.getConstructor().getDeclarationDescriptor() in getAllTypeVariables()
|
type -> type.getConstructor().getDeclarationDescriptor() in getAllTypeVariables()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KotlinType.getNestedTypeVariables(original: Boolean = true): List<TypeParameterDescriptor> {
|
override fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor> {
|
||||||
return getNestedArguments().map { typeProjection ->
|
return type.getNestedArguments().map { typeProjection ->
|
||||||
typeProjection.getType().getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor
|
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||||
}.filterNotNull().filter { if (original) it in originalToVariables.keySet() else it in getAllTypeVariables() }
|
}.filterNotNull().filter { if (original) it in originalToVariables.keys else it in getAllTypeVariables() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copy(filterConstraintPosition: (ConstraintPosition) -> Boolean): ConstraintSystem {
|
override fun copy(filterConstraintPosition: (ConstraintPosition) -> Boolean): ConstraintSystem {
|
||||||
@@ -349,7 +350,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
typeBounds.addBound(bound)
|
typeBounds.addBound(bound)
|
||||||
|
|
||||||
if (!bound.isProper) {
|
if (!bound.isProper) {
|
||||||
for (dependentTypeVariable in bound.constrainingType.getNestedTypeVariables(original = false)) {
|
for (dependentTypeVariable in getNestedTypeVariables(bound.constrainingType, original = false)) {
|
||||||
val dependentBounds = usedInBounds.getOrPut(dependentTypeVariable) { arrayListOf() }
|
val dependentBounds = usedInBounds.getOrPut(dependentTypeVariable) { arrayListOf() }
|
||||||
dependentBounds.add(bound)
|
dependentBounds.add(bound)
|
||||||
}
|
}
|
||||||
@@ -489,7 +490,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
if (typeBounds.isFixed) return
|
if (typeBounds.isFixed) return
|
||||||
typeBounds.setFixed()
|
typeBounds.setFixed()
|
||||||
|
|
||||||
val nestedTypeVariables = typeBounds.bounds.flatMap { it.constrainingType.getNestedTypeVariables(original = false) }
|
val nestedTypeVariables = typeBounds.bounds.flatMap { getNestedTypeVariables(it.constrainingType, original = false) }
|
||||||
nestedTypeVariables.forEach { fixVariable(it) }
|
nestedTypeVariables.forEach { fixVariable(it) }
|
||||||
|
|
||||||
val value = typeBounds.value ?: return
|
val value = typeBounds.value ?: return
|
||||||
@@ -497,7 +498,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
addBound(typeVariable, value, TypeBounds.BoundKind.EXACT_BOUND, ConstraintContext(ConstraintPositionKind.FROM_COMPLETER.position()))
|
addBound(typeVariable, value, TypeBounds.BoundKind.EXACT_BOUND, ConstraintContext(ConstraintPositionKind.FROM_COMPLETER.position()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fixVariables() {
|
override fun fixVariables() {
|
||||||
// todo variables should be fixed in the right order
|
// todo variables should be fixed in the right order
|
||||||
val (external, functionTypeParameters) = getAllTypeVariables().partition { externalTypeParameters.contains(it) }
|
val (external, functionTypeParameters) = getAllTypeVariables().partition { externalTypeParameters.contains(it) }
|
||||||
external.forEach { fixVariable(it) }
|
external.forEach { fixVariable(it) }
|
||||||
|
|||||||
+2
@@ -91,4 +91,6 @@ public interface ConstraintSystemStatus {
|
|||||||
public fun hasTypeInferenceIncorporationError(): Boolean
|
public fun hasTypeInferenceIncorporationError(): Boolean
|
||||||
|
|
||||||
public fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError(): Boolean
|
public fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError(): Boolean
|
||||||
|
|
||||||
|
public val constraintErrors: List<ConstraintError>
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-6
@@ -21,12 +21,13 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.Constra
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.EXACT_BOUND
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.CompoundConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.CompoundConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
||||||
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
||||||
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
||||||
@@ -57,7 +58,8 @@ fun ConstraintSystemImpl.incorporateBound(newBound: Bound) {
|
|||||||
addBound(getMyTypeVariable(constrainingType)!!, typeVariable.correspondingType, newBound.kind.reverse(), context)
|
addBound(getMyTypeVariable(constrainingType)!!, typeVariable.correspondingType, newBound.kind.reverse(), context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
constrainingType.getNestedTypeVariables().forEach {
|
|
||||||
|
getNestedTypeVariables(constrainingType, original = true).forEach {
|
||||||
val boundsForNestedVariable = getTypeBounds(it).bounds
|
val boundsForNestedVariable = getTypeBounds(it).bounds
|
||||||
for (index in boundsForNestedVariable.indices) {
|
for (index in boundsForNestedVariable.indices) {
|
||||||
generateNewBound(newBound, boundsForNestedVariable[index])
|
generateNewBound(newBound, boundsForNestedVariable[index])
|
||||||
@@ -98,7 +100,7 @@ private fun ConstraintSystemImpl.generateNewBound(bound: Bound, substitution: Bo
|
|||||||
|
|
||||||
fun addNewBound(newConstrainingType: KotlinType, newBoundKind: BoundKind) {
|
fun addNewBound(newConstrainingType: KotlinType, newBoundKind: BoundKind) {
|
||||||
// We don't generate new recursive constraints
|
// We don't generate new recursive constraints
|
||||||
val nestedTypeVariables = newConstrainingType.getNestedTypeVariables(original = false)
|
val nestedTypeVariables = getNestedTypeVariables(newConstrainingType, original = false)
|
||||||
if (nestedTypeVariables.contains(bound.typeVariable)) return
|
if (nestedTypeVariables.contains(bound.typeVariable)) return
|
||||||
|
|
||||||
// We don't generate constraint if a type variable was substituted twice
|
// We don't generate constraint if a type variable was substituted twice
|
||||||
|
|||||||
Reference in New Issue
Block a user