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:
Alexander Udalov
2015-11-11 21:29:44 +03:00
parent cb05a8d58d
commit d4664af4e5
7 changed files with 74 additions and 52 deletions
@@ -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()
);
}
};
}
@@ -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(
@@ -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.
@@ -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)
}
}
@@ -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()