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(); KotlinType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
if (returnType == null) return; 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 traceToResolveConventionMethods =
TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods"); TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods");
OverloadResolutionResults<FunctionDescriptor> OverloadResolutionResults<FunctionDescriptor>
@@ -368,15 +372,12 @@ public class DelegatedPropertyResolver {
FunctionDescriptor descriptor = getMethodResults.getResultingDescriptor(); FunctionDescriptor descriptor = getMethodResults.getResultingDescriptor();
KotlinType returnTypeOfGetMethod = descriptor.getReturnType(); KotlinType returnTypeOfGetMethod = descriptor.getReturnType();
if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) { if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) {
TypeSubstitutor substitutor = KotlinType returnTypeInSystem = typeVariableSubstitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT);
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);
if (returnTypeInSystem != null) { if (returnTypeInSystem != null) {
constraintSystem.addSupertypeConstraint(expectedType, returnTypeInSystem, FROM_COMPLETER.position()); constraintSystem.addSupertypeConstraint(expectedType, returnTypeInSystem, FROM_COMPLETER.position());
} }
} }
addConstraintForThisValue(constraintSystem, descriptor); addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
} }
if (!propertyDescriptor.isVar()) return; if (!propertyDescriptor.isVar()) return;
@@ -399,9 +400,12 @@ public class DelegatedPropertyResolver {
if (!noExpectedType(expectedType)) { if (!noExpectedType(expectedType)) {
constraintSystem.addSubtypeConstraint( 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); 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 extensionReceiver = propertyDescriptor.getExtensionReceiverParameter();
ReceiverParameterDescriptor dispatchReceiver = propertyDescriptor.getDispatchReceiverParameter(); ReceiverParameterDescriptor dispatchReceiver = propertyDescriptor.getDispatchReceiverParameter();
KotlinType typeOfThis = KotlinType typeOfThis =
@@ -424,7 +432,11 @@ public class DelegatedPropertyResolver {
if (valueParameters.isEmpty()) return; if (valueParameters.isEmpty()) return;
ValueParameterDescriptor valueParameterForThis = valueParameters.get(0); 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) { if (receiverArgument is ExpressionReceiver) {
receiverType = updateResultTypeForSmartCasts(receiverType, receiverArgument.expression, context) 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() val constraintSystem = builder.build()
@@ -100,6 +104,16 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
return OTHER_ERROR 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( fun addConstraintForValueArgument(
valueArgument: ValueArgument, valueArgument: ValueArgument,
valueParameterDescriptor: ValueParameterDescriptor, valueParameterDescriptor: ValueParameterDescriptor,
@@ -108,7 +122,6 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
context: CallCandidateResolutionContext<*>, context: CallCandidateResolutionContext<*>,
resolveFunctionArgumentBodies: ResolveArgumentsMode resolveFunctionArgumentBodies: ResolveArgumentsMode
) { ) {
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument) val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
val argumentExpression = valueArgument.getArgumentExpression() val argumentExpression = valueArgument.getArgumentExpression()
@@ -124,7 +137,11 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
if (addConstraintForNestedCall(argumentExpression, constraintPosition, builder, newContext, effectiveExpectedType)) return if (addConstraintForNestedCall(argumentExpression, constraintPosition, builder, newContext, effectiveExpectedType)) return
val type = updateResultTypeForSmartCasts(typeInfoForCall.type, argumentExpression, context.replaceDataFlowInfo(dataFlowInfoForArgument)) 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( private fun addConstraintForNestedCall(
@@ -157,7 +174,12 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
val freshVariables = returnType.getNestedTypeParameters().map { conversion[it] }.filterNotNull() val freshVariables = returnType.getNestedTypeParameters().map { conversion[it] }.filterNotNull()
builder.registerTypeVariables(resultingCall.call.toHandle(), freshVariables, external = true) 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 return true
} }
@@ -222,6 +244,9 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
val dataFlowInfoForArguments = context.candidateCall.dataFlowInfoForArguments val dataFlowInfoForArguments = context.candidateCall.dataFlowInfoForArguments
val dataFlowInfoForArgument = dataFlowInfoForArguments.getInfo(valueArgument) 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 //todo analyze function literal body once in 'dependent' mode, then complete it with respect to expected type
val hasExpectedReturnType = !hasUnknownReturnType(expectedType) val hasExpectedReturnType = !hasUnknownReturnType(expectedType)
val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index) val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index)
@@ -239,7 +264,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
val type = argumentTypeResolver.getFunctionLiteralTypeInfo( val type = argumentTypeResolver.getFunctionLiteralTypeInfo(
argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
if (!mismatch[0]) { if (!mismatch[0]) {
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, position) constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
temporaryToResolveFunctionLiteral.commit() temporaryToResolveFunctionLiteral.commit()
return return
} }
@@ -248,7 +273,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
val newContext = context.replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument) val newContext = context.replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
.replaceContextDependency(INDEPENDENT) .replaceContextDependency(INDEPENDENT)
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type 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( private fun <D : CallableDescriptor> addConstraintForCallableReference(
@@ -264,7 +289,11 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
if (!ReflectionTypes.isCallableType(expectedType)) return if (!ReflectionTypes.isCallableType(expectedType)) return
val resolvedType = getResolvedTypeForCallableReference(callableReference, context, expectedType, valueArgument) val resolvedType = getResolvedTypeForCallableReference(callableReference, context, expectedType, valueArgument)
val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index) 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( 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)` * 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. * 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. * 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 usedInBounds = HashMap<TypeVariable, MutableList<TypeBounds.Bound>>()
internal val errors = ArrayList<ConstraintError>() internal val errors = ArrayList<ConstraintError>()
internal val initialConstraints = ArrayList<Constraint>() internal val initialConstraints = ArrayList<Constraint>()
internal val descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeVariable>()
override val typeVariableSubstitutors = LinkedHashMap<CallHandle, TypeSubstitutor>() 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 { private fun storeSubstitutor(call: CallHandle, substitutor: TypeSubstitutor): TypeSubstitutor {
if (typeVariableSubstitutors.containsKey(call)) { if (typeVariableSubstitutors.containsKey(call)) {
throw IllegalStateException("Type variables for the same call can be registered only once: $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)) { for ((descriptor, typeVariable) in typeParameters.zip(typeVariables)) {
allTypeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable)) allTypeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable))
descriptorToVariable[descriptor] = typeVariable
} }
for ((typeVariable, typeBounds) in allTypeParameterBounds) { for ((typeVariable, typeBounds) in allTypeParameterBounds) {
@@ -124,9 +111,8 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
addConstraint(SUB_TYPE, subjectType, constrainingType, ConstraintContext(constraintPosition, initial = true)) addConstraint(SUB_TYPE, subjectType, constrainingType, ConstraintContext(constraintPosition, initial = true))
} }
override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) { override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType?, constraintPosition: ConstraintPosition) {
val newSubjectType = descriptorToVariableSubstitutor.substitute(subjectType, Variance.INVARIANT) addConstraint(SUB_TYPE, constrainingType, subjectType, ConstraintContext(constraintPosition, initial = true))
addConstraint(SUB_TYPE, constrainingType, newSubjectType, ConstraintContext(constraintPosition, initial = true))
} }
fun addConstraint( fun addConstraint(
@@ -387,9 +373,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
} }
override fun build(): ConstraintSystem { override fun build(): ConstraintSystem {
return ConstraintSystemImpl( return ConstraintSystemImpl(allTypeParameterBounds, usedInBounds, errors, initialConstraints, typeVariableSubstitutors)
allTypeParameterBounds, usedInBounds, errors, initialConstraints, descriptorToVariable, typeVariableSubstitutors
)
} }
} }
@@ -38,7 +38,6 @@ internal class ConstraintSystemImpl(
private val usedInBounds: Map<TypeVariable, MutableList<TypeBounds.Bound>>, private val usedInBounds: Map<TypeVariable, MutableList<TypeBounds.Bound>>,
private val errors: List<ConstraintError>, private val errors: List<ConstraintError>,
private val initialConstraints: List<ConstraintSystemBuilderImpl.Constraint>, private val initialConstraints: List<ConstraintSystemBuilderImpl.Constraint>,
private val descriptorToVariable: Map<TypeParameterDescriptor, TypeVariable>,
private val typeVariableSubstitutors: Map<CallHandle, TypeSubstitutor> private val typeVariableSubstitutors: Map<CallHandle, TypeSubstitutor>
) : ConstraintSystem { ) : ConstraintSystem {
private val localTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl> private val localTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl>
@@ -107,13 +106,15 @@ internal class ConstraintSystemImpl(
} }
override val typeParameterDescriptors: Set<TypeParameterDescriptor> override val typeParameterDescriptors: Set<TypeParameterDescriptor>
get() = descriptorToVariable.keys get() = typeVariables.map { it.originalTypeParameter }.toSet()
override val typeVariables: Set<TypeVariable> override val typeVariables: Set<TypeVariable>
get() = allTypeParameterBounds.keys get() = allTypeParameterBounds.keys
override fun descriptorToVariable(call: CallHandle, descriptor: TypeParameterDescriptor): TypeVariable = 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 { override fun getTypeBounds(typeVariable: TypeVariable): TypeBoundsImpl {
return allTypeParameterBounds[typeVariable] ?: return allTypeParameterBounds[typeVariable] ?:
@@ -167,7 +168,6 @@ internal class ConstraintSystemImpl(
result.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) }) result.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) })
result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) }) result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
result.descriptorToVariable.putAll(descriptorToVariable)
result.typeVariableSubstitutors.putAll(typeVariableSubstitutors) result.typeVariableSubstitutors.putAll(typeVariableSubstitutors)
return result return result
@@ -186,8 +186,8 @@ public class TypeIntersector {
processAllTypeParameters(withParameters, Variance.INVARIANT, processor); processAllTypeParameters(withParameters, Variance.INVARIANT, processor);
processAllTypeParameters(expected, Variance.INVARIANT, processor); processAllTypeParameters(expected, Variance.INVARIANT, processor);
ConstraintSystem.Builder constraintSystem = new ConstraintSystemBuilderImpl(); ConstraintSystem.Builder constraintSystem = new ConstraintSystemBuilderImpl();
constraintSystem.registerTypeVariables(CallHandle.NONE.INSTANCE, parameters.keySet(), false); TypeSubstitutor substitutor = constraintSystem.registerTypeVariables(CallHandle.NONE.INSTANCE, parameters.keySet(), false);
constraintSystem.addSubtypeConstraint(withParameters, expected, SPECIAL.position()); constraintSystem.addSubtypeConstraint(withParameters, substitutor.substitute(expected, Variance.INVARIANT), SPECIAL.position());
return constraintSystem.build().getStatus().isSuccessful(); return constraintSystem.build().getStatus().isSuccessful();
} }
@@ -118,17 +118,14 @@ class FuzzyType(
val builder = ConstraintSystemBuilderImpl() val builder = ConstraintSystemBuilderImpl()
val typeVariableSubstitutor = builder.registerTypeVariables(CallHandle.NONE, freeParameters + otherType.freeParameters) 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) { when (matchKind) {
MatchKind.IS_SUBTYPE -> builder.addSubtypeConstraint( MatchKind.IS_SUBTYPE ->
typeVariableSubstitutor.substitute(type, Variance.INVARIANT), builder.addSubtypeConstraint(typeInSystem, otherTypeInSystem, ConstraintPositionKind.RECEIVER_POSITION.position())
otherType.type, MatchKind.IS_SUPERTYPE ->
ConstraintPositionKind.RECEIVER_POSITION.position() builder.addSubtypeConstraint(otherTypeInSystem, typeInSystem, ConstraintPositionKind.RECEIVER_POSITION.position())
)
MatchKind.IS_SUPERTYPE -> builder.addSubtypeConstraint(
typeVariableSubstitutor.substitute(otherType.type, Variance.INVARIANT),
type,
ConstraintPositionKind.RECEIVER_POSITION.position()
)
} }
builder.fixVariables() builder.fixVariables()