Get rid of originalToVariableSubstitutor and descriptorToVariable
Move the composite substitutor to GenericCandidateResolver where it was used, other places don't need it since they know the exact call (or NO_CALL), the substitutor for which should be used
This commit is contained in:
@@ -356,6 +356,10 @@ public class DelegatedPropertyResolver {
|
||||
KotlinType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
|
||||
if (returnType == null) return;
|
||||
|
||||
TypeSubstitutor typeVariableSubstitutor =
|
||||
constraintSystem.getTypeVariableSubstitutors().get(TypeVariableKt.toHandle(resolvedCall.getCall()));
|
||||
assert typeVariableSubstitutor != null : "No substitutor in the system for call: " + resolvedCall.getCall();
|
||||
|
||||
TemporaryBindingTrace traceToResolveConventionMethods =
|
||||
TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods");
|
||||
OverloadResolutionResults<FunctionDescriptor>
|
||||
@@ -368,15 +372,12 @@ public class DelegatedPropertyResolver {
|
||||
FunctionDescriptor descriptor = getMethodResults.getResultingDescriptor();
|
||||
KotlinType returnTypeOfGetMethod = descriptor.getReturnType();
|
||||
if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) {
|
||||
TypeSubstitutor substitutor =
|
||||
constraintSystem.getTypeVariableSubstitutors().get(TypeVariableKt.toHandle(resolvedCall.getCall()));
|
||||
assert substitutor != null : "No substitutor in the system for call: " + resolvedCall.getCall();
|
||||
KotlinType returnTypeInSystem = substitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT);
|
||||
KotlinType returnTypeInSystem = typeVariableSubstitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT);
|
||||
if (returnTypeInSystem != null) {
|
||||
constraintSystem.addSupertypeConstraint(expectedType, returnTypeInSystem, FROM_COMPLETER.position());
|
||||
}
|
||||
}
|
||||
addConstraintForThisValue(constraintSystem, descriptor);
|
||||
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
|
||||
}
|
||||
if (!propertyDescriptor.isVar()) return;
|
||||
|
||||
@@ -399,9 +400,12 @@ public class DelegatedPropertyResolver {
|
||||
|
||||
if (!noExpectedType(expectedType)) {
|
||||
constraintSystem.addSubtypeConstraint(
|
||||
expectedType, valueParameterForThis.getType(), FROM_COMPLETER.position());
|
||||
expectedType,
|
||||
typeVariableSubstitutor.substitute(valueParameterForThis.getType(), Variance.INVARIANT),
|
||||
FROM_COMPLETER.position()
|
||||
);
|
||||
}
|
||||
addConstraintForThisValue(constraintSystem, descriptor);
|
||||
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -412,7 +416,11 @@ public class DelegatedPropertyResolver {
|
||||
results.getResultCode() == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
|
||||
}
|
||||
|
||||
private void addConstraintForThisValue(ConstraintSystem.Builder constraintSystem, FunctionDescriptor resultingDescriptor) {
|
||||
private void addConstraintForThisValue(
|
||||
ConstraintSystem.Builder constraintSystem,
|
||||
TypeSubstitutor typeVariableSubstitutor,
|
||||
FunctionDescriptor resultingDescriptor
|
||||
) {
|
||||
ReceiverParameterDescriptor extensionReceiver = propertyDescriptor.getExtensionReceiverParameter();
|
||||
ReceiverParameterDescriptor dispatchReceiver = propertyDescriptor.getDispatchReceiverParameter();
|
||||
KotlinType typeOfThis =
|
||||
@@ -424,7 +432,11 @@ public class DelegatedPropertyResolver {
|
||||
if (valueParameters.isEmpty()) return;
|
||||
ValueParameterDescriptor valueParameterForThis = valueParameters.get(0);
|
||||
|
||||
constraintSystem.addSubtypeConstraint(typeOfThis, valueParameterForThis.getType(), FROM_COMPLETER.position());
|
||||
constraintSystem.addSubtypeConstraint(
|
||||
typeOfThis,
|
||||
typeVariableSubstitutor.substitute(valueParameterForThis.getType(), Variance.INVARIANT),
|
||||
FROM_COMPLETER.position()
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+36
-7
@@ -86,7 +86,11 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
if (receiverArgument is ExpressionReceiver) {
|
||||
receiverType = updateResultTypeForSmartCasts(receiverType, receiverArgument.expression, context)
|
||||
}
|
||||
builder.addSubtypeConstraint(receiverType, receiverParameter.type, RECEIVER_POSITION.position())
|
||||
builder.addSubtypeConstraint(
|
||||
receiverType,
|
||||
builder.compositeSubstitutor().substitute(receiverParameter.type, Variance.INVARIANT),
|
||||
RECEIVER_POSITION.position()
|
||||
)
|
||||
}
|
||||
|
||||
val constraintSystem = builder.build()
|
||||
@@ -100,6 +104,16 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
return OTHER_ERROR
|
||||
}
|
||||
|
||||
// Creates a substitutor which maps types to their representation in the constraint system.
|
||||
// In case when some type parameter descriptor is represented by more than one variable in the system, the behavior is undefined.
|
||||
private fun ConstraintSystem.Builder.compositeSubstitutor(): TypeSubstitutor {
|
||||
return TypeSubstitutor.create(object : TypeSubstitution() {
|
||||
override fun get(key: KotlinType): TypeProjection? {
|
||||
return typeVariableSubstitutors.values.reversed().asSequence().mapNotNull { it.substitution.get(key) }.firstOrNull()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun addConstraintForValueArgument(
|
||||
valueArgument: ValueArgument,
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
@@ -108,7 +122,6 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
context: CallCandidateResolutionContext<*>,
|
||||
resolveFunctionArgumentBodies: ResolveArgumentsMode
|
||||
) {
|
||||
|
||||
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
|
||||
val argumentExpression = valueArgument.getArgumentExpression()
|
||||
|
||||
@@ -124,7 +137,11 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
if (addConstraintForNestedCall(argumentExpression, constraintPosition, builder, newContext, effectiveExpectedType)) return
|
||||
|
||||
val type = updateResultTypeForSmartCasts(typeInfoForCall.type, argumentExpression, context.replaceDataFlowInfo(dataFlowInfoForArgument))
|
||||
builder.addSubtypeConstraint(type, effectiveExpectedType, constraintPosition)
|
||||
builder.addSubtypeConstraint(
|
||||
type,
|
||||
builder.compositeSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT),
|
||||
constraintPosition
|
||||
)
|
||||
}
|
||||
|
||||
private fun addConstraintForNestedCall(
|
||||
@@ -157,7 +174,12 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val freshVariables = returnType.getNestedTypeParameters().map { conversion[it] }.filterNotNull()
|
||||
builder.registerTypeVariables(resultingCall.call.toHandle(), freshVariables, external = true)
|
||||
|
||||
builder.addSubtypeConstraint(candidateWithFreshVariables.returnType, effectiveExpectedType, constraintPosition)
|
||||
builder.addSubtypeConstraint(
|
||||
candidateWithFreshVariables.returnType,
|
||||
builder.compositeSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT),
|
||||
constraintPosition
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -222,6 +244,9 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val dataFlowInfoForArguments = context.candidateCall.dataFlowInfoForArguments
|
||||
val dataFlowInfoForArgument = dataFlowInfoForArguments.getInfo(valueArgument)
|
||||
|
||||
val effectiveExpectedTypeInSystem =
|
||||
constraintSystem.typeVariableSubstitutors[context.call.toHandle()]?.substitute(effectiveExpectedType, Variance.INVARIANT)
|
||||
|
||||
//todo analyze function literal body once in 'dependent' mode, then complete it with respect to expected type
|
||||
val hasExpectedReturnType = !hasUnknownReturnType(expectedType)
|
||||
val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index)
|
||||
@@ -239,7 +264,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(
|
||||
argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
|
||||
if (!mismatch[0]) {
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, position)
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
|
||||
temporaryToResolveFunctionLiteral.commit()
|
||||
return
|
||||
}
|
||||
@@ -248,7 +273,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val newContext = context.replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
|
||||
.replaceContextDependency(INDEPENDENT)
|
||||
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, position)
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> addConstraintForCallableReference(
|
||||
@@ -264,7 +289,11 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
if (!ReflectionTypes.isCallableType(expectedType)) return
|
||||
val resolvedType = getResolvedTypeForCallableReference(callableReference, context, expectedType, valueArgument)
|
||||
val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index)
|
||||
constraintSystem.addSubtypeConstraint(resolvedType, effectiveExpectedType, position)
|
||||
constraintSystem.addSubtypeConstraint(
|
||||
resolvedType,
|
||||
constraintSystem.typeVariableSubstitutors[context.call.toHandle()]?.substitute(effectiveExpectedType, Variance.INVARIANT),
|
||||
position
|
||||
)
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> getExpectedTypeForCallableReference(
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ interface ConstraintSystem {
|
||||
* 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)
|
||||
fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType?, constraintPosition: ConstraintPosition)
|
||||
|
||||
/**
|
||||
* Adds a constraint that the constraining type is a supertype of the subject type.
|
||||
|
||||
+3
-19
@@ -51,21 +51,9 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
||||
internal val usedInBounds = HashMap<TypeVariable, MutableList<TypeBounds.Bound>>()
|
||||
internal val errors = ArrayList<ConstraintError>()
|
||||
internal val initialConstraints = ArrayList<Constraint>()
|
||||
internal val descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeVariable>()
|
||||
|
||||
override val typeVariableSubstitutors = LinkedHashMap<CallHandle, TypeSubstitutor>()
|
||||
|
||||
private val descriptorToVariableSubstitutor: TypeSubstitutor by lazy {
|
||||
TypeSubstitutor.create(object : TypeConstructorSubstitution() {
|
||||
override fun get(key: TypeConstructor): TypeProjection? {
|
||||
val descriptor = key.declarationDescriptor
|
||||
if (descriptor !is TypeParameterDescriptor) return null
|
||||
val typeVariable = descriptorToVariable[descriptor] ?: return null
|
||||
return TypeProjectionImpl(typeVariable.type)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun storeSubstitutor(call: CallHandle, substitutor: TypeSubstitutor): TypeSubstitutor {
|
||||
if (typeVariableSubstitutors.containsKey(call)) {
|
||||
throw IllegalStateException("Type variables for the same call can be registered only once: $call")
|
||||
@@ -97,7 +85,6 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
||||
|
||||
for ((descriptor, typeVariable) in typeParameters.zip(typeVariables)) {
|
||||
allTypeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable))
|
||||
descriptorToVariable[descriptor] = typeVariable
|
||||
}
|
||||
|
||||
for ((typeVariable, typeBounds) in allTypeParameterBounds) {
|
||||
@@ -124,9 +111,8 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
||||
addConstraint(SUB_TYPE, subjectType, constrainingType, ConstraintContext(constraintPosition, initial = true))
|
||||
}
|
||||
|
||||
override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
||||
val newSubjectType = descriptorToVariableSubstitutor.substitute(subjectType, Variance.INVARIANT)
|
||||
addConstraint(SUB_TYPE, constrainingType, newSubjectType, ConstraintContext(constraintPosition, initial = true))
|
||||
override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType?, constraintPosition: ConstraintPosition) {
|
||||
addConstraint(SUB_TYPE, constrainingType, subjectType, ConstraintContext(constraintPosition, initial = true))
|
||||
}
|
||||
|
||||
fun addConstraint(
|
||||
@@ -387,9 +373,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
||||
}
|
||||
|
||||
override fun build(): ConstraintSystem {
|
||||
return ConstraintSystemImpl(
|
||||
allTypeParameterBounds, usedInBounds, errors, initialConstraints, descriptorToVariable, typeVariableSubstitutors
|
||||
)
|
||||
return ConstraintSystemImpl(allTypeParameterBounds, usedInBounds, errors, initialConstraints, typeVariableSubstitutors)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -38,7 +38,6 @@ internal class ConstraintSystemImpl(
|
||||
private val usedInBounds: Map<TypeVariable, MutableList<TypeBounds.Bound>>,
|
||||
private val errors: List<ConstraintError>,
|
||||
private val initialConstraints: List<ConstraintSystemBuilderImpl.Constraint>,
|
||||
private val descriptorToVariable: Map<TypeParameterDescriptor, TypeVariable>,
|
||||
private val typeVariableSubstitutors: Map<CallHandle, TypeSubstitutor>
|
||||
) : ConstraintSystem {
|
||||
private val localTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl>
|
||||
@@ -107,13 +106,15 @@ internal class ConstraintSystemImpl(
|
||||
}
|
||||
|
||||
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
|
||||
get() = descriptorToVariable.keys
|
||||
get() = typeVariables.map { it.originalTypeParameter }.toSet()
|
||||
|
||||
override val typeVariables: Set<TypeVariable>
|
||||
get() = allTypeParameterBounds.keys
|
||||
|
||||
override fun descriptorToVariable(call: CallHandle, descriptor: TypeParameterDescriptor): TypeVariable =
|
||||
descriptorToVariable[descriptor] ?: throw IllegalArgumentException("Unknown descriptor: $descriptor, call: $call")
|
||||
typeVariables.firstOrNull {
|
||||
it.call == call && it.originalTypeParameter == descriptor
|
||||
} ?: throw IllegalArgumentException("Unknown descriptor: $descriptor, call: $call")
|
||||
|
||||
override fun getTypeBounds(typeVariable: TypeVariable): TypeBoundsImpl {
|
||||
return allTypeParameterBounds[typeVariable] ?:
|
||||
@@ -167,7 +168,6 @@ internal class ConstraintSystemImpl(
|
||||
result.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) })
|
||||
|
||||
result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
|
||||
result.descriptorToVariable.putAll(descriptorToVariable)
|
||||
result.typeVariableSubstitutors.putAll(typeVariableSubstitutors)
|
||||
|
||||
return result
|
||||
|
||||
@@ -186,8 +186,8 @@ public class TypeIntersector {
|
||||
processAllTypeParameters(withParameters, Variance.INVARIANT, processor);
|
||||
processAllTypeParameters(expected, Variance.INVARIANT, processor);
|
||||
ConstraintSystem.Builder constraintSystem = new ConstraintSystemBuilderImpl();
|
||||
constraintSystem.registerTypeVariables(CallHandle.NONE.INSTANCE, parameters.keySet(), false);
|
||||
constraintSystem.addSubtypeConstraint(withParameters, expected, SPECIAL.position());
|
||||
TypeSubstitutor substitutor = constraintSystem.registerTypeVariables(CallHandle.NONE.INSTANCE, parameters.keySet(), false);
|
||||
constraintSystem.addSubtypeConstraint(withParameters, substitutor.substitute(expected, Variance.INVARIANT), SPECIAL.position());
|
||||
|
||||
return constraintSystem.build().getStatus().isSuccessful();
|
||||
}
|
||||
|
||||
@@ -118,17 +118,14 @@ class FuzzyType(
|
||||
val builder = ConstraintSystemBuilderImpl()
|
||||
val typeVariableSubstitutor = builder.registerTypeVariables(CallHandle.NONE, freeParameters + otherType.freeParameters)
|
||||
|
||||
val typeInSystem = typeVariableSubstitutor.substitute(type, Variance.INVARIANT)
|
||||
val otherTypeInSystem = typeVariableSubstitutor.substitute(otherType.type, Variance.INVARIANT)
|
||||
|
||||
when (matchKind) {
|
||||
MatchKind.IS_SUBTYPE -> builder.addSubtypeConstraint(
|
||||
typeVariableSubstitutor.substitute(type, Variance.INVARIANT),
|
||||
otherType.type,
|
||||
ConstraintPositionKind.RECEIVER_POSITION.position()
|
||||
)
|
||||
MatchKind.IS_SUPERTYPE -> builder.addSubtypeConstraint(
|
||||
typeVariableSubstitutor.substitute(otherType.type, Variance.INVARIANT),
|
||||
type,
|
||||
ConstraintPositionKind.RECEIVER_POSITION.position()
|
||||
)
|
||||
MatchKind.IS_SUBTYPE ->
|
||||
builder.addSubtypeConstraint(typeInSystem, otherTypeInSystem, ConstraintPositionKind.RECEIVER_POSITION.position())
|
||||
MatchKind.IS_SUPERTYPE ->
|
||||
builder.addSubtypeConstraint(otherTypeInSystem, typeInSystem, ConstraintPositionKind.RECEIVER_POSITION.position())
|
||||
}
|
||||
|
||||
builder.fixVariables()
|
||||
|
||||
Reference in New Issue
Block a user