Move mutating methods of ConstraintSystem to Builder
Extract immutable ConstraintSystemSnapshot from ConstraintSystemImpl
This commit is contained in:
@@ -352,7 +352,7 @@ public class DelegatedPropertyResolver {
|
||||
return new ConstraintSystemCompleter() {
|
||||
@Override
|
||||
public void completeConstraintSystem(
|
||||
@NotNull ConstraintSystem constraintSystem, @NotNull ResolvedCall<?> resolvedCall
|
||||
@NotNull ConstraintSystem.Builder constraintSystem, @NotNull ResolvedCall<?> resolvedCall
|
||||
) {
|
||||
KotlinType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
|
||||
if (returnType == null) return;
|
||||
@@ -407,7 +407,7 @@ public class DelegatedPropertyResolver {
|
||||
results.getResultCode() == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
|
||||
}
|
||||
|
||||
private void addConstraintForThisValue(ConstraintSystem constraintSystem, FunctionDescriptor resultingDescriptor) {
|
||||
private void addConstraintForThisValue(ConstraintSystem.Builder constraintSystem, FunctionDescriptor resultingDescriptor) {
|
||||
ReceiverParameterDescriptor extensionReceiver = propertyDescriptor.getExtensionReceiverParameter();
|
||||
ReceiverParameterDescriptor dispatchReceiver = propertyDescriptor.getDispatchReceiverParameter();
|
||||
KotlinType typeOfThis =
|
||||
|
||||
@@ -139,16 +139,19 @@ public class CallCompleter(
|
||||
expectedType: KotlinType,
|
||||
trace: BindingTrace
|
||||
) {
|
||||
fun updateSystemIfSuccessful(update: (ConstraintSystem) -> Boolean) {
|
||||
val copy = constraintSystem!!.copy()
|
||||
if (update(copy)) {
|
||||
setConstraintSystem(copy)
|
||||
fun updateSystemIfNeeded(buildSystemWithAdditionalConstraints: (ConstraintSystem.Builder) -> ConstraintSystem?) {
|
||||
val system = buildSystemWithAdditionalConstraints(constraintSystem!!.toBuilder())
|
||||
if (system != null) {
|
||||
setConstraintSystem(system)
|
||||
}
|
||||
}
|
||||
|
||||
val returnType = getCandidateDescriptor().getReturnType()
|
||||
if (returnType != null) {
|
||||
constraintSystem!!.addSupertypeConstraint(expectedType, returnType, EXPECTED_TYPE_POSITION.position())
|
||||
updateSystemIfNeeded { builder ->
|
||||
builder.addSupertypeConstraint(expectedType, returnType, EXPECTED_TYPE_POSITION.position())
|
||||
builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
val constraintSystemCompleter = trace[CONSTRAINT_SYSTEM_COMPLETER, getCall().getCalleeExpression()]
|
||||
@@ -156,24 +159,29 @@ public class CallCompleter(
|
||||
// todo improve error reporting with errors in constraints from completer
|
||||
// todo add constraints from completer unconditionally; improve constraints from completer for generic methods
|
||||
// add the constraints only if they don't lead to errors (except errors from upper bounds to improve diagnostics)
|
||||
updateSystemIfSuccessful {
|
||||
system ->
|
||||
constraintSystemCompleter.completeConstraintSystem(system, this)
|
||||
!system.filterConstraintsOut(TYPE_BOUND_POSITION).getStatus().hasOnlyErrorsDerivedFrom(FROM_COMPLETER)
|
||||
updateSystemIfNeeded { builder ->
|
||||
constraintSystemCompleter.completeConstraintSystem(builder, this)
|
||||
val system = builder.build()
|
||||
val status = system.filterConstraintsOut(TYPE_BOUND_POSITION).getStatus()
|
||||
if (status.hasOnlyErrorsDerivedFrom(FROM_COMPLETER)) null else system
|
||||
}
|
||||
}
|
||||
|
||||
if (returnType != null && expectedType === TypeUtils.UNIT_EXPECTED_TYPE) {
|
||||
updateSystemIfSuccessful {
|
||||
system ->
|
||||
system.addSupertypeConstraint(builtIns.getUnitType(), returnType, EXPECTED_TYPE_POSITION.position())
|
||||
system.getStatus().isSuccessful()
|
||||
updateSystemIfNeeded { builder ->
|
||||
builder.addSupertypeConstraint(builtIns.getUnitType(), returnType, EXPECTED_TYPE_POSITION.position())
|
||||
val system = builder.build()
|
||||
if (system.getStatus().isSuccessful()) system else null
|
||||
}
|
||||
}
|
||||
|
||||
constraintSystem!!.fixVariables()
|
||||
|
||||
setResultingSubstitutor(constraintSystem!!.getResultingSubstitutor())
|
||||
val builder = constraintSystem!!.toBuilder()
|
||||
builder.fixVariables()
|
||||
val system = builder.build()
|
||||
setConstraintSystem(system)
|
||||
|
||||
setResultingSubstitutor(system.getResultingSubstitutor())
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> MutableResolvedCall<D>.updateResolutionStatusFromConstraintSystem(
|
||||
|
||||
@@ -70,7 +70,7 @@ private fun getReturnTypeForCallable(type: KotlinType) =
|
||||
|
||||
private fun CallableDescriptor.hasReturnTypeDependentOnUninferredParams(constraintSystem: ConstraintSystem): Boolean {
|
||||
val returnType = returnType ?: return false
|
||||
val nestedTypeVariables = constraintSystem.getNestedTypeVariables(returnType, original = true)
|
||||
val nestedTypeVariables = constraintSystem.getNestedTypeVariables(returnType)
|
||||
return nestedTypeVariables.any { constraintSystem.getTypeBounds(it).value == null }
|
||||
}
|
||||
|
||||
|
||||
+25
-20
@@ -53,8 +53,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val candidateCall = context.candidateCall
|
||||
val candidate = candidateCall.candidateDescriptor
|
||||
|
||||
val constraintSystem = ConstraintSystemImpl()
|
||||
candidateCall.setConstraintSystem(constraintSystem)
|
||||
val builder = ConstraintSystemImpl()
|
||||
|
||||
// If the call is recursive, e.g.
|
||||
// fun foo<T>(t : T) : T = foo(t)
|
||||
@@ -65,7 +64,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate)
|
||||
|
||||
val conversionToOriginal = candidateWithFreshVariables.typeParameters.zip(candidate.typeParameters).toMap()
|
||||
constraintSystem.registerTypeVariables(candidateWithFreshVariables.typeParameters, { conversionToOriginal[it]!! })
|
||||
builder.registerTypeVariables(candidateWithFreshVariables.typeParameters, { conversionToOriginal[it]!! })
|
||||
|
||||
val substituteDontCare = makeConstantSubstitutor(candidate.typeParameters, DONT_CARE)
|
||||
|
||||
@@ -79,8 +78,9 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
// Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare)
|
||||
// and throw the results away
|
||||
// We'll type check the arguments later, with the inferred types expected
|
||||
addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare,
|
||||
constraintSystem, context, SHAPE_FUNCTION_ARGUMENTS)
|
||||
addConstraintForValueArgument(
|
||||
valueArgument, valueParameterDescriptor, substituteDontCare, builder, context, SHAPE_FUNCTION_ARGUMENTS
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,9 +97,12 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
if (receiverArgument is ExpressionReceiver) {
|
||||
receiverType = updateResultTypeForSmartCasts(receiverType, receiverArgument.expression, context)
|
||||
}
|
||||
constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.type, RECEIVER_POSITION.position())
|
||||
builder.addSubtypeConstraint(receiverType, receiverParameter.type, RECEIVER_POSITION.position())
|
||||
}
|
||||
|
||||
val constraintSystem = builder.build()
|
||||
candidateCall.setConstraintSystem(constraintSystem)
|
||||
|
||||
// Solution
|
||||
val hasContradiction = constraintSystem.getStatus().hasContradiction()
|
||||
if (!hasContradiction) {
|
||||
@@ -112,7 +115,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
valueArgument: ValueArgument,
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
substitutor: TypeSubstitutor,
|
||||
constraintSystem: ConstraintSystem,
|
||||
builder: ConstraintSystem.Builder,
|
||||
context: CallCandidateResolutionContext<*>,
|
||||
resolveFunctionArgumentBodies: ResolveArgumentsMode
|
||||
) {
|
||||
@@ -129,16 +132,16 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
|
||||
val constraintPosition = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index)
|
||||
|
||||
if (addConstraintForNestedCall(argumentExpression, constraintPosition, constraintSystem, newContext, effectiveExpectedType)) return
|
||||
if (addConstraintForNestedCall(argumentExpression, constraintPosition, builder, newContext, effectiveExpectedType)) return
|
||||
|
||||
val type = updateResultTypeForSmartCasts(typeInfoForCall.type, argumentExpression, context.replaceDataFlowInfo(dataFlowInfoForArgument))
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, constraintPosition)
|
||||
builder.addSubtypeConstraint(type, effectiveExpectedType, constraintPosition)
|
||||
}
|
||||
|
||||
private fun addConstraintForNestedCall(
|
||||
argumentExpression: KtExpression?,
|
||||
constraintPosition: ConstraintPosition,
|
||||
constraintSystem: ConstraintSystem,
|
||||
builder: ConstraintSystem.Builder,
|
||||
context: CallCandidateResolutionContext<*>,
|
||||
effectiveExpectedType: KotlinType
|
||||
): Boolean {
|
||||
@@ -153,7 +156,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val candidateDescriptor = resultingCall.candidateDescriptor
|
||||
val returnType = candidateDescriptor.returnType ?: return false
|
||||
|
||||
val nestedTypeVariables = argumentConstraintSystem.getNestedTypeVariables(returnType, original = true)
|
||||
val nestedTypeVariables = argumentConstraintSystem.getNestedTypeVariables(returnType)
|
||||
|
||||
// we add an additional type variable only if no information is inferred for it.
|
||||
// otherwise we add currently inferred return type as before
|
||||
@@ -163,9 +166,9 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val conversion = candidateDescriptor.typeParameters.zip(candidateWithFreshVariables.typeParameters).toMap()
|
||||
|
||||
val freshVariables = nestedTypeVariables.map { conversion[it] }.filterNotNull()
|
||||
constraintSystem.registerTypeVariables(freshVariables, external = true)
|
||||
builder.registerTypeVariables(freshVariables, external = true)
|
||||
|
||||
constraintSystem.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition)
|
||||
builder.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -188,7 +191,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
|
||||
fun <D : CallableDescriptor> completeTypeInferenceDependentOnFunctionArgumentsForCall(context: CallCandidateResolutionContext<D>) {
|
||||
val resolvedCall = context.candidateCall
|
||||
val constraintSystem = resolvedCall.constraintSystem ?: return
|
||||
val constraintSystem = resolvedCall.constraintSystem?.toBuilder() ?: return
|
||||
|
||||
// constraints for function literals
|
||||
// Value parameters
|
||||
@@ -204,20 +207,22 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
}
|
||||
}
|
||||
}
|
||||
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor())
|
||||
val resultingSystem = constraintSystem.build()
|
||||
resolvedCall.setConstraintSystem(resultingSystem)
|
||||
resolvedCall.setResultingSubstitutor(resultingSystem.getResultingSubstitutor())
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> addConstraintForFunctionLiteral(
|
||||
functionLiteral: KtFunction,
|
||||
valueArgument: ValueArgument,
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
constraintSystem: ConstraintSystem,
|
||||
constraintSystem: ConstraintSystem.Builder,
|
||||
context: CallCandidateResolutionContext<D>
|
||||
) {
|
||||
val argumentExpression = valueArgument.getArgumentExpression() ?: return
|
||||
|
||||
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
|
||||
var expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
|
||||
var expectedType = constraintSystem.build().getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
|
||||
if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) {
|
||||
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false)
|
||||
}
|
||||
@@ -261,7 +266,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
callableReference: KtCallableReferenceExpression,
|
||||
valueArgument: ValueArgument,
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
constraintSystem: ConstraintSystem,
|
||||
constraintSystem: ConstraintSystem.Builder,
|
||||
context: CallCandidateResolutionContext<D>
|
||||
) {
|
||||
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
|
||||
@@ -275,11 +280,11 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
|
||||
private fun <D : CallableDescriptor> getExpectedTypeForCallableReference(
|
||||
callableReference: KtCallableReferenceExpression,
|
||||
constraintSystem: ConstraintSystem,
|
||||
constraintSystem: ConstraintSystem.Builder,
|
||||
context: CallCandidateResolutionContext<D>,
|
||||
effectiveExpectedType: KotlinType
|
||||
): KotlinType? {
|
||||
val substitutedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
|
||||
val substitutedType = constraintSystem.build().getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
|
||||
if (substitutedType != null && !TypeUtils.isDontCarePlaceholder(substitutedType))
|
||||
return substitutedType
|
||||
|
||||
|
||||
+43
-39
@@ -23,47 +23,19 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFr
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
public interface ConstraintSystem {
|
||||
/**
|
||||
* Registers variables in a constraint system.
|
||||
* The type variables for the corresponding function are local, the type variables of inner arguments calls are non-local.
|
||||
*/
|
||||
public fun registerTypeVariables(
|
||||
typeVariables: Collection<TypeParameterDescriptor>,
|
||||
mapToOriginal: (TypeParameterDescriptor) -> TypeParameterDescriptor = { it },
|
||||
external: Boolean = false
|
||||
)
|
||||
|
||||
interface ConstraintSystem {
|
||||
/**
|
||||
* Returns a set of all non-external registered type variables.
|
||||
*/
|
||||
public fun getTypeVariables(): Set<TypeParameterDescriptor>
|
||||
fun getTypeVariables(): Set<TypeParameterDescriptor>
|
||||
|
||||
/**
|
||||
* Adds a constraint that the constraining type is a subtype of the subject type.
|
||||
* Asserts that only subject type may contain registered type variables.
|
||||
*
|
||||
* For example, for `fun <T> id(t: T) {}` to infer `T` in invocation `id(1)`
|
||||
* the constraint "Int is a subtype of T" should be generated where T is a subject type, and Int is a constraining type.
|
||||
*/
|
||||
public fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition)
|
||||
|
||||
/**
|
||||
* Adds a constraint that the constraining type is a supertype of the subject type.
|
||||
* Asserts that only subject type may contain registered type variables.
|
||||
*
|
||||
* For example, for `fun <T> create(): T` to infer `T` in invocation `val i: Int = create()`
|
||||
* the constraint "Int is a supertype of T" should be generated where T is a subject type, and Int is a constraining type.
|
||||
*/
|
||||
public fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition)
|
||||
|
||||
public fun getStatus(): ConstraintSystemStatus
|
||||
fun getStatus(): ConstraintSystemStatus
|
||||
|
||||
/**
|
||||
* Returns the resulting type constraints of solving the constraint system for specific type variable.
|
||||
* Throws IllegalArgumentException if the type variable was not registered.
|
||||
*/
|
||||
public fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds
|
||||
fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds
|
||||
|
||||
/**
|
||||
* Returns the result of solving the constraint system (mapping from the type variable to the resulting type projection).
|
||||
@@ -74,26 +46,58 @@ public interface ConstraintSystem {
|
||||
* If the addition of the 'expected type' constraint made the system fail,
|
||||
* this constraint is not included in the resulting substitution.
|
||||
*/
|
||||
public fun getResultingSubstitutor(): TypeSubstitutor
|
||||
fun getResultingSubstitutor(): TypeSubstitutor
|
||||
|
||||
/**
|
||||
* Returns the current result of solving the constraint system (mapping from the type variable to the resulting type projection).
|
||||
* If there is no information for type parameter, returns type projection for DONT_CARE type.
|
||||
*/
|
||||
public fun getCurrentSubstitutor(): TypeSubstitutor
|
||||
fun getCurrentSubstitutor(): TypeSubstitutor
|
||||
|
||||
/**
|
||||
* Returns the substitution only for type parameters that have result values, otherwise returns the type parameter itself.
|
||||
*/
|
||||
public fun getPartialSubstitutor(): TypeSubstitutor
|
||||
fun getPartialSubstitutor(): TypeSubstitutor
|
||||
|
||||
public fun copy(filterConstraintPosition: (ConstraintPosition) -> Boolean = { true }): ConstraintSystem
|
||||
fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor>
|
||||
|
||||
public fun fixVariables()
|
||||
fun toBuilder(filterConstraintPosition: (ConstraintPosition) -> Boolean = { true }): Builder
|
||||
|
||||
public fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor>
|
||||
interface Builder {
|
||||
/**
|
||||
* Registers variables in a constraint system.
|
||||
* The type variables for the corresponding function are local, the type variables of inner arguments calls are non-local.
|
||||
*/
|
||||
fun registerTypeVariables(
|
||||
typeVariables: Collection<TypeParameterDescriptor>,
|
||||
mapToOriginal: (TypeParameterDescriptor) -> TypeParameterDescriptor = { it },
|
||||
external: Boolean = false
|
||||
)
|
||||
|
||||
/**
|
||||
* Adds a constraint that the constraining type is a subtype of the subject type.
|
||||
* Asserts that only subject type may contain registered type variables.
|
||||
*
|
||||
* For example, for `fun <T> id(t: T) {}` to infer `T` in invocation `id(1)`
|
||||
* the constraint "Int is a subtype of T" should be generated where T is a subject type, and Int is a constraining type.
|
||||
*/
|
||||
fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition)
|
||||
|
||||
/**
|
||||
* Adds a constraint that the constraining type is a supertype of the subject type.
|
||||
* Asserts that only subject type may contain registered type variables.
|
||||
*
|
||||
* For example, for `fun <T> create(): T` to infer `T` in invocation `val i: Int = create()`
|
||||
* the constraint "Int is a supertype of T" should be generated where T is a subject type, and Int is a constraining type.
|
||||
*/
|
||||
fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition)
|
||||
|
||||
fun fixVariables()
|
||||
|
||||
fun build(): ConstraintSystem
|
||||
}
|
||||
}
|
||||
|
||||
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
|
||||
return copy { !it.derivedFrom(excludePositionKind) }
|
||||
return toBuilder { !it.derivedFrom(excludePositionKind) }.build()
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
|
||||
public interface ConstraintSystemCompleter {
|
||||
void completeConstraintSystem(
|
||||
@NotNull ConstraintSystem constraintSystem,
|
||||
@NotNull ConstraintSystem.Builder constraintSystem,
|
||||
@NotNull ResolvedCall<?> resolvedCall
|
||||
);
|
||||
}
|
||||
|
||||
+20
-144
@@ -27,21 +27,21 @@ import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFrom
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasInternalAnnotationForResolve
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isInternalAnnotationForResolve
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
||||
import org.jetbrains.kotlin.types.typeUtil.isDefaultBound
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import java.util.*
|
||||
|
||||
public class ConstraintSystemImpl : ConstraintSystem {
|
||||
public class ConstraintSystemImpl : ConstraintSystem.Builder {
|
||||
|
||||
data class Constraint(val kind: ConstraintKind, val subtype: KotlinType, val superType: KotlinType, val position: ConstraintPosition)
|
||||
|
||||
@@ -52,94 +52,18 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
|
||||
fun ConstraintKind.toBound() = if (this == SUB_TYPE) UPPER_BOUND else EXACT_BOUND
|
||||
|
||||
private val allTypeParameterBounds = LinkedHashMap<TypeParameterDescriptor, TypeBoundsImpl>()
|
||||
private val externalTypeParameters = HashSet<TypeParameterDescriptor>()
|
||||
private val localTypeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>
|
||||
get() = if (externalTypeParameters.isEmpty()) allTypeParameterBounds
|
||||
else allTypeParameterBounds.filter { !externalTypeParameters.contains(it.key) }
|
||||
|
||||
private val cachedTypeForVariable = HashMap<TypeParameterDescriptor, KotlinType>()
|
||||
|
||||
private val usedInBounds = HashMap<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>()
|
||||
|
||||
private val errors = ArrayList<ConstraintError>()
|
||||
|
||||
private val initialConstraints = ArrayList<Constraint>()
|
||||
internal val allTypeParameterBounds = LinkedHashMap<TypeParameterDescriptor, TypeBoundsImpl>()
|
||||
internal val externalTypeParameters = HashSet<TypeParameterDescriptor>()
|
||||
internal val cachedTypeForVariable = HashMap<TypeParameterDescriptor, KotlinType>()
|
||||
internal val usedInBounds = HashMap<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>()
|
||||
internal val errors = ArrayList<ConstraintError>()
|
||||
internal val initialConstraints = ArrayList<Constraint>()
|
||||
internal val originalToVariables = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
|
||||
internal val variablesToOriginal = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
|
||||
|
||||
private val originalToVariablesSubstitutor: TypeSubstitutor by lazy {
|
||||
createTypeSubstitutor { originalToVariables[it] }
|
||||
}
|
||||
private val originalToVariables = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
|
||||
private val variablesToOriginal = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
|
||||
|
||||
private val constraintSystemStatus = object : ConstraintSystemStatus {
|
||||
// for debug ConstraintsUtil.getDebugMessageForStatus might be used
|
||||
|
||||
override fun isSuccessful() = !hasContradiction() && !hasUnknownParameters()
|
||||
|
||||
override fun hasContradiction() = hasParameterConstraintError() || hasConflictingConstraints()
|
||||
|| hasCannotCaptureTypesError() || hasTypeInferenceIncorporationError()
|
||||
|
||||
|
||||
override fun hasViolatedUpperBound() = !isSuccessful() && filterConstraintsOut(TYPE_BOUND_POSITION).getStatus().isSuccessful()
|
||||
|
||||
override fun hasConflictingConstraints() = localTypeParameterBounds.values().any { it.values.size() > 1 }
|
||||
|
||||
override fun hasUnknownParameters() =
|
||||
localTypeParameterBounds.values().any { it.values.isEmpty() } || hasTypeParameterWithUnsatisfiedOnlyInputTypesError()
|
||||
|
||||
override fun hasParameterConstraintError() = errors.any { it is ParameterConstraintError }
|
||||
|
||||
override fun hasOnlyErrorsDerivedFrom(kind: ConstraintPositionKind): Boolean {
|
||||
if (isSuccessful()) return false
|
||||
if (filterConstraintsOut(kind).getStatus().isSuccessful()) return true
|
||||
return errors.isNotEmpty() && errors.all { it.constraintPosition.derivedFrom(kind) }
|
||||
}
|
||||
|
||||
override fun hasErrorInConstrainingTypes() = errors.any { it is ErrorInConstrainingType }
|
||||
|
||||
override fun hasCannotCaptureTypesError() = errors.any { it is CannotCapture }
|
||||
|
||||
override fun hasTypeInferenceIncorporationError() = errors.any { it is TypeInferenceError } || !satisfyInitialConstraints()
|
||||
|
||||
override fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError() =
|
||||
localTypeParameterBounds.values.any { it.typeVariable.hasOnlyInputTypesAnnotation() && it.value == null }
|
||||
|
||||
override val constraintErrors: List<ConstraintError>
|
||||
get() = errors
|
||||
}
|
||||
|
||||
private fun getParameterToInferredValueMap(
|
||||
typeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>,
|
||||
getDefaultTypeProjection: (TypeParameterDescriptor) -> TypeProjection,
|
||||
substituteOriginal: Boolean
|
||||
): Map<TypeParameterDescriptor, TypeProjection> {
|
||||
val substitutionContext = HashMap<TypeParameterDescriptor, TypeProjection>()
|
||||
for ((variable, typeBounds) in typeParameterBounds) {
|
||||
val typeProjection: TypeProjection
|
||||
val value = typeBounds.value
|
||||
val typeParameter = if (substituteOriginal) variablesToOriginal[variable]!! else variable
|
||||
if (value != null && !TypeUtils.containsSpecialType(value, DONT_CARE)) {
|
||||
typeProjection = TypeProjectionImpl(value)
|
||||
}
|
||||
else {
|
||||
typeProjection = getDefaultTypeProjection(typeParameter)
|
||||
}
|
||||
substitutionContext.put(typeParameter, typeProjection)
|
||||
}
|
||||
return substitutionContext
|
||||
}
|
||||
|
||||
private fun replaceUninferredBy(
|
||||
getDefaultValue: (TypeParameterDescriptor) -> TypeProjection,
|
||||
substituteOriginal: Boolean
|
||||
): TypeSubstitutor {
|
||||
val parameterToInferredValueMap = getParameterToInferredValueMap(allTypeParameterBounds, getDefaultValue, substituteOriginal)
|
||||
val substitution = TypeConstructorSubstitution.createByParametersMap(parameterToInferredValueMap)
|
||||
return SubstitutionFilteringInternalResolveAnnotations(substitution).buildSubstitutor()
|
||||
}
|
||||
|
||||
override fun getStatus(): ConstraintSystemStatus = constraintSystemStatus
|
||||
|
||||
override fun registerTypeVariables(
|
||||
typeVariables: Collection<TypeParameterDescriptor>,
|
||||
@@ -172,30 +96,12 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
type -> type.getConstructor().getDeclarationDescriptor() in getAllTypeVariables()
|
||||
}
|
||||
|
||||
override fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor> {
|
||||
fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor> {
|
||||
return type.getNestedArguments().map { typeProjection ->
|
||||
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||
}.filterNotNull().filter { if (original) it in originalToVariables.keys else it in getAllTypeVariables() }
|
||||
}
|
||||
|
||||
override fun copy(filterConstraintPosition: (ConstraintPosition) -> Boolean): ConstraintSystem {
|
||||
val newSystem = ConstraintSystemImpl()
|
||||
for ((typeParameter, typeBounds) in allTypeParameterBounds) {
|
||||
newSystem.allTypeParameterBounds.put(typeParameter, typeBounds.filter(filterConstraintPosition))
|
||||
}
|
||||
newSystem.usedInBounds.putAll(usedInBounds.map {
|
||||
val (variable, bounds) = it
|
||||
variable to bounds.filterTo(arrayListOf<Bound>()) { filterConstraintPosition(it.position )}
|
||||
}.toMap())
|
||||
newSystem.externalTypeParameters.addAll(externalTypeParameters )
|
||||
newSystem.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) })
|
||||
|
||||
newSystem.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
|
||||
newSystem.originalToVariables.putAll(originalToVariables)
|
||||
newSystem.variablesToOriginal.putAll(variablesToOriginal)
|
||||
return newSystem
|
||||
}
|
||||
|
||||
override fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
||||
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return
|
||||
|
||||
@@ -423,13 +329,11 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
addBound(typeVariable, capturedType, EXACT_BOUND, constraintContext)
|
||||
}
|
||||
|
||||
override fun getTypeVariables() = originalToVariables.keySet()
|
||||
|
||||
fun getAllTypeVariables() = allTypeParameterBounds.keySet()
|
||||
|
||||
fun getBoundsUsedIn(typeVariable: TypeParameterDescriptor): List<Bound> = usedInBounds[typeVariable] ?: emptyList()
|
||||
|
||||
override fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl {
|
||||
fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl {
|
||||
val variableForOriginal = originalToVariables[typeVariable]
|
||||
if (variableForOriginal != null && variableForOriginal != typeVariable) {
|
||||
return getTypeBounds(variableForOriginal)
|
||||
@@ -449,42 +353,10 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
return if (typeParameterDescriptor != null && isMyTypeVariable(typeParameterDescriptor)) typeParameterDescriptor else null
|
||||
}
|
||||
|
||||
override fun getResultingSubstitutor() =
|
||||
getSubstitutor(substituteOriginal = true) { TypeProjectionImpl(ErrorUtils.createUninferredParameterType(it)) }
|
||||
|
||||
override fun getCurrentSubstitutor() =
|
||||
getSubstitutor(substituteOriginal = true) { TypeProjectionImpl(TypeUtils.DONT_CARE) }
|
||||
|
||||
override fun getPartialSubstitutor() =
|
||||
getSubstitutor(substituteOriginal = true) { TypeProjectionImpl(it.correspondingType) }
|
||||
|
||||
private fun getSubstitutor(substituteOriginal: Boolean, getDefaultValue: (TypeParameterDescriptor) -> TypeProjection) =
|
||||
replaceUninferredBy(getDefaultValue, substituteOriginal).setApproximateCapturedTypes()
|
||||
|
||||
private fun storeInitialConstraint(constraintKind: ConstraintKind, subType: KotlinType, superType: KotlinType, position: ConstraintPosition) {
|
||||
initialConstraints.add(Constraint(constraintKind, subType, superType, position))
|
||||
}
|
||||
|
||||
private fun satisfyInitialConstraints(): Boolean {
|
||||
fun KotlinType.substitute(): KotlinType? {
|
||||
val substitutor = getSubstitutor(substituteOriginal = false) { TypeProjectionImpl(ErrorUtils.createUninferredParameterType(it)) }
|
||||
return substitutor.substitute(this, Variance.INVARIANT) ?: return null
|
||||
}
|
||||
return initialConstraints.all {
|
||||
constraint ->
|
||||
val resultSubType = constraint.subtype.substitute()?.let {
|
||||
// the call might be done via safe access, so we check for notNullable receiver type;
|
||||
// 'unsafe call' error is reported otherwise later
|
||||
if (constraint.position.kind != ConstraintPositionKind.RECEIVER_POSITION) it else it.makeNotNullable()
|
||||
} ?: return false
|
||||
val resultSuperType = constraint.superType.substitute() ?: return false
|
||||
when (constraint.kind) {
|
||||
SUB_TYPE -> KotlinTypeChecker.DEFAULT.isSubtypeOf(resultSubType, resultSuperType)
|
||||
EQUAL -> KotlinTypeChecker.DEFAULT.equalTypes(resultSubType, resultSuperType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun fixVariable(typeVariable: TypeParameterDescriptor) {
|
||||
val typeBounds = getTypeBounds(typeVariable)
|
||||
if (typeBounds.isFixed) return
|
||||
@@ -505,6 +377,10 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
functionTypeParameters.forEach { fixVariable(it) }
|
||||
}
|
||||
|
||||
override fun build(): ConstraintSystem {
|
||||
return ConstraintSystemSnapshot(allTypeParameterBounds, externalTypeParameters, usedInBounds, errors, initialConstraints,
|
||||
originalToVariables, variablesToOriginal)
|
||||
}
|
||||
}
|
||||
|
||||
fun createTypeForFunctionPlaceholder(
|
||||
@@ -532,7 +408,7 @@ fun createTypeForFunctionPlaceholder(
|
||||
return functionPlaceholder.builtIns.getFunctionType(Annotations.EMPTY, receiverType, newArgumentTypes, DONT_CARE)
|
||||
}
|
||||
|
||||
private fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor {
|
||||
internal fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor {
|
||||
return TypeSubstitutor.create(SubstitutionWithCapturedTypeApproximation(getSubstitution()))
|
||||
}
|
||||
|
||||
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.inference
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.EQUAL
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFrom
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation
|
||||
import org.jetbrains.kotlin.resolve.scopes.KtScope
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import java.util.*
|
||||
|
||||
class ConstraintSystemSnapshot(
|
||||
private val allTypeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>,
|
||||
private val externalTypeParameters: Set<TypeParameterDescriptor>,
|
||||
private val usedInBounds: Map<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>,
|
||||
private val errors: List<ConstraintError>,
|
||||
private val initialConstraints: List<ConstraintSystemImpl.Constraint>,
|
||||
private val originalToVariables: Map<TypeParameterDescriptor, TypeParameterDescriptor>,
|
||||
private val variablesToOriginal: Map<TypeParameterDescriptor, TypeParameterDescriptor>
|
||||
) : ConstraintSystem {
|
||||
private val localTypeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>
|
||||
get() = if (externalTypeParameters.isEmpty()) allTypeParameterBounds
|
||||
else allTypeParameterBounds.filter { !externalTypeParameters.contains(it.key) }
|
||||
|
||||
private val constraintSystemStatus = object : ConstraintSystemStatus {
|
||||
// for debug ConstraintsUtil.getDebugMessageForStatus might be used
|
||||
|
||||
override fun isSuccessful() = !hasContradiction() && !hasUnknownParameters()
|
||||
|
||||
override fun hasContradiction() = hasParameterConstraintError() || hasConflictingConstraints()
|
||||
|| hasCannotCaptureTypesError() || hasTypeInferenceIncorporationError()
|
||||
|
||||
override fun hasViolatedUpperBound() = !isSuccessful() && filterConstraintsOut(TYPE_BOUND_POSITION).getStatus().isSuccessful()
|
||||
|
||||
override fun hasConflictingConstraints() = localTypeParameterBounds.values.any { it.values.size > 1 }
|
||||
|
||||
override fun hasUnknownParameters() =
|
||||
localTypeParameterBounds.values.any { it.values.isEmpty() } || hasTypeParameterWithUnsatisfiedOnlyInputTypesError()
|
||||
|
||||
override fun hasParameterConstraintError() = errors.any { it is ParameterConstraintError }
|
||||
|
||||
override fun hasOnlyErrorsDerivedFrom(kind: ConstraintPositionKind): Boolean {
|
||||
if (isSuccessful()) return false
|
||||
if (filterConstraintsOut(kind).getStatus().isSuccessful()) return true
|
||||
return errors.isNotEmpty() && errors.all { it.constraintPosition.derivedFrom(kind) }
|
||||
}
|
||||
|
||||
override fun hasErrorInConstrainingTypes() = errors.any { it is ErrorInConstrainingType }
|
||||
|
||||
override fun hasCannotCaptureTypesError() = errors.any { it is CannotCapture }
|
||||
|
||||
override fun hasTypeInferenceIncorporationError() = errors.any { it is TypeInferenceError } || !satisfyInitialConstraints()
|
||||
|
||||
override fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError() =
|
||||
localTypeParameterBounds.values.any { it.typeVariable.hasOnlyInputTypesAnnotation() && it.value == null }
|
||||
|
||||
override val constraintErrors: List<ConstraintError>
|
||||
get() = errors
|
||||
}
|
||||
|
||||
private fun getParameterToInferredValueMap(
|
||||
typeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>,
|
||||
getDefaultTypeProjection: (TypeParameterDescriptor) -> TypeProjection,
|
||||
substituteOriginal: Boolean
|
||||
): Map<TypeParameterDescriptor, TypeProjection> {
|
||||
val substitutionContext = HashMap<TypeParameterDescriptor, TypeProjection>()
|
||||
for ((variable, typeBounds) in typeParameterBounds) {
|
||||
val typeProjection: TypeProjection
|
||||
val value = typeBounds.value
|
||||
val typeParameter = if (substituteOriginal) variablesToOriginal[variable]!! else variable
|
||||
if (value != null && !TypeUtils.containsSpecialType(value, DONT_CARE)) {
|
||||
typeProjection = TypeProjectionImpl(value)
|
||||
}
|
||||
else {
|
||||
typeProjection = getDefaultTypeProjection(typeParameter)
|
||||
}
|
||||
substitutionContext.put(typeParameter, typeProjection)
|
||||
}
|
||||
return substitutionContext
|
||||
}
|
||||
|
||||
private fun replaceUninferredBy(
|
||||
getDefaultValue: (TypeParameterDescriptor) -> TypeProjection,
|
||||
substituteOriginal: Boolean
|
||||
): TypeSubstitutor {
|
||||
val parameterToInferredValueMap = getParameterToInferredValueMap(allTypeParameterBounds, getDefaultValue, substituteOriginal)
|
||||
val substitution = TypeConstructorSubstitution.createByParametersMap(parameterToInferredValueMap)
|
||||
return SubstitutionFilteringInternalResolveAnnotations(substitution).buildSubstitutor()
|
||||
}
|
||||
|
||||
override fun getStatus(): ConstraintSystemStatus = constraintSystemStatus
|
||||
|
||||
override fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> {
|
||||
return type.getNestedArguments().map { typeProjection ->
|
||||
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||
}.filterNotNull().filter { it in getTypeVariables() }
|
||||
}
|
||||
|
||||
override fun getTypeVariables() = originalToVariables.keys
|
||||
|
||||
override fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl {
|
||||
val variableForOriginal = originalToVariables[typeVariable]
|
||||
if (variableForOriginal != null && variableForOriginal != typeVariable) {
|
||||
return getTypeBounds(variableForOriginal)
|
||||
}
|
||||
return allTypeParameterBounds[typeVariable] ?:
|
||||
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
||||
}
|
||||
|
||||
override fun getResultingSubstitutor() =
|
||||
getSubstitutor(substituteOriginal = true) { TypeProjectionImpl(ErrorUtils.createUninferredParameterType(it)) }
|
||||
|
||||
override fun getCurrentSubstitutor() =
|
||||
getSubstitutor(substituteOriginal = true) { TypeProjectionImpl(TypeUtils.DONT_CARE) }
|
||||
|
||||
override fun getPartialSubstitutor() =
|
||||
getSubstitutor(substituteOriginal = true) {
|
||||
TypeProjectionImpl(KotlinTypeImpl.create(Annotations.EMPTY, it.typeConstructor, false, listOf(), KtScope.Empty))
|
||||
}
|
||||
|
||||
private fun getSubstitutor(substituteOriginal: Boolean, getDefaultValue: (TypeParameterDescriptor) -> TypeProjection) =
|
||||
replaceUninferredBy(getDefaultValue, substituteOriginal).setApproximateCapturedTypes()
|
||||
|
||||
private fun satisfyInitialConstraints(): Boolean {
|
||||
fun KotlinType.substitute(): KotlinType? {
|
||||
val substitutor = getSubstitutor(substituteOriginal = false) { TypeProjectionImpl(ErrorUtils.createUninferredParameterType(it)) }
|
||||
return substitutor.substitute(this, Variance.INVARIANT) ?: return null
|
||||
}
|
||||
return initialConstraints.all {
|
||||
constraint ->
|
||||
val resultSubType = constraint.subtype.substitute()?.let {
|
||||
// the call might be done via safe access, so we check for notNullable receiver type;
|
||||
// 'unsafe call' error is reported otherwise later
|
||||
if (constraint.position.kind != ConstraintPositionKind.RECEIVER_POSITION) it else it.makeNotNullable()
|
||||
} ?: return false
|
||||
val resultSuperType = constraint.superType.substitute() ?: return false
|
||||
when (constraint.kind) {
|
||||
SUB_TYPE -> KotlinTypeChecker.DEFAULT.isSubtypeOf(resultSubType, resultSuperType)
|
||||
EQUAL -> KotlinTypeChecker.DEFAULT.equalTypes(resultSubType, resultSuperType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun toBuilder(filterConstraintPosition: (ConstraintPosition) -> Boolean): ConstraintSystem.Builder {
|
||||
val result = ConstraintSystemImpl()
|
||||
for ((typeParameter, typeBounds) in allTypeParameterBounds) {
|
||||
result.allTypeParameterBounds.put(typeParameter, typeBounds.filter(filterConstraintPosition))
|
||||
}
|
||||
result.usedInBounds.putAll(usedInBounds.map {
|
||||
val (variable, bounds) = it
|
||||
variable to bounds.filterTo(arrayListOf<TypeBounds.Bound>()) { filterConstraintPosition(it.position )}
|
||||
}.toMap())
|
||||
result.externalTypeParameters.addAll(externalTypeParameters )
|
||||
result.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) })
|
||||
|
||||
result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
|
||||
result.originalToVariables.putAll(originalToVariables)
|
||||
result.variablesToOriginal.putAll(variablesToOriginal)
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl;
|
||||
import org.jetbrains.kotlin.resolve.scopes.ChainedScope;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
@@ -184,7 +185,7 @@ public class TypeIntersector {
|
||||
};
|
||||
processAllTypeParameters(withParameters, Variance.INVARIANT, processor);
|
||||
processAllTypeParameters(expected, Variance.INVARIANT, processor);
|
||||
ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl();
|
||||
ConstraintSystem.Builder constraintSystem = new ConstraintSystemImpl();
|
||||
constraintSystem.registerTypeVariables(parameters.keySet(), new Function1<TypeParameterDescriptor, TypeParameterDescriptor>() {
|
||||
@Override
|
||||
public TypeParameterDescriptor invoke(TypeParameterDescriptor descriptor) {
|
||||
@@ -193,7 +194,7 @@ public class TypeIntersector {
|
||||
}, false);
|
||||
constraintSystem.addSubtypeConstraint(withParameters, expected, SPECIAL.position());
|
||||
|
||||
return constraintSystem.getStatus().isSuccessful();
|
||||
return constraintSystem.build().getStatus().isSuccessful();
|
||||
}
|
||||
|
||||
private static void processAllTypeParameters(KotlinType type, Variance howThisTypeIsUsed, Function1<TypeParameterUsage, Unit> result) {
|
||||
|
||||
+11
-8
@@ -76,12 +76,12 @@ abstract public class AbstractConstraintSystemTest() : KotlinLiteFixture() {
|
||||
val constraintsFile = File(filePath)
|
||||
val constraintsFileText = constraintsFile.readLines()
|
||||
|
||||
val constraintSystem = ConstraintSystemImpl()
|
||||
val builder = ConstraintSystemImpl()
|
||||
|
||||
val variables = parseVariables(constraintsFileText)
|
||||
val fixVariables = constraintsFileText.contains("FIX_VARIABLES")
|
||||
val typeParameterDescriptors = variables.map { testDeclarations.getParameterDescriptor(it) }
|
||||
constraintSystem.registerTypeVariables(typeParameterDescriptors)
|
||||
builder.registerTypeVariables(typeParameterDescriptors)
|
||||
|
||||
val constraints = parseConstraints(constraintsFileText)
|
||||
fun KotlinType.assertNotError(): KotlinType {
|
||||
@@ -93,17 +93,20 @@ abstract public class AbstractConstraintSystemTest() : KotlinLiteFixture() {
|
||||
val secondType = testDeclarations.getType(constraint.secondType).assertNotError()
|
||||
val context = ConstraintContext(SPECIAL.position(), initial = true)
|
||||
when (constraint.kind) {
|
||||
MyConstraintKind.SUBTYPE -> constraintSystem.addSubtypeConstraint(firstType, secondType, context.position)
|
||||
MyConstraintKind.SUPERTYPE -> constraintSystem.addSupertypeConstraint(firstType, secondType, context.position)
|
||||
MyConstraintKind.EQUAL -> constraintSystem.addConstraint(
|
||||
MyConstraintKind.SUBTYPE -> builder.addSubtypeConstraint(firstType, secondType, context.position)
|
||||
MyConstraintKind.SUPERTYPE -> builder.addSupertypeConstraint(firstType, secondType, context.position)
|
||||
MyConstraintKind.EQUAL -> builder.addConstraint(
|
||||
ConstraintSystemImpl.ConstraintKind.EQUAL, firstType, secondType, context)
|
||||
}
|
||||
}
|
||||
if (fixVariables) constraintSystem.fixVariables()
|
||||
|
||||
val resultingStatus = Renderers.RENDER_CONSTRAINT_SYSTEM_SHORT.render(constraintSystem)
|
||||
if (fixVariables) builder.fixVariables()
|
||||
|
||||
val resultingSubstitutor = constraintSystem.getResultingSubstitutor()
|
||||
val system = builder.build()
|
||||
|
||||
val resultingStatus = Renderers.RENDER_CONSTRAINT_SYSTEM_SHORT.render(system)
|
||||
|
||||
val resultingSubstitutor = system.getResultingSubstitutor()
|
||||
val result = typeParameterDescriptors.map {
|
||||
val parameterType = testDeclarations.getType(it.getName().asString())
|
||||
val resultType = resultingSubstitutor.substitute(parameterType, Variance.INVARIANT)
|
||||
|
||||
@@ -116,16 +116,18 @@ class FuzzyType(
|
||||
return if (type.checkInheritance(otherType.type)) TypeSubstitutor.EMPTY else null
|
||||
}
|
||||
|
||||
val constraintSystem = ConstraintSystemImpl()
|
||||
constraintSystem.registerTypeVariables(freeParameters)
|
||||
constraintSystem.registerTypeVariables(otherType.freeParameters)
|
||||
val builder = ConstraintSystemImpl()
|
||||
builder.registerTypeVariables(freeParameters)
|
||||
builder.registerTypeVariables(otherType.freeParameters)
|
||||
|
||||
when (matchKind) {
|
||||
MatchKind.IS_SUBTYPE -> constraintSystem.addSubtypeConstraint(type, otherType.type, ConstraintPositionKind.RECEIVER_POSITION.position())
|
||||
MatchKind.IS_SUPERTYPE -> constraintSystem.addSubtypeConstraint(otherType.type, type, ConstraintPositionKind.RECEIVER_POSITION.position())
|
||||
MatchKind.IS_SUBTYPE -> builder.addSubtypeConstraint(type, otherType.type, ConstraintPositionKind.RECEIVER_POSITION.position())
|
||||
MatchKind.IS_SUPERTYPE -> builder.addSubtypeConstraint(otherType.type, type, ConstraintPositionKind.RECEIVER_POSITION.position())
|
||||
}
|
||||
|
||||
constraintSystem.fixVariables()
|
||||
builder.fixVariables()
|
||||
|
||||
val constraintSystem = builder.build()
|
||||
|
||||
if (constraintSystem.getStatus().hasContradiction()) return null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user