Remove ConstraintSystem.Builder.addSupertypeConstraint
Use addSubtypeConstraint everywhere to reduce confusion
This commit is contained in:
@@ -374,7 +374,7 @@ public class DelegatedPropertyResolver {
|
|||||||
if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) {
|
if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) {
|
||||||
KotlinType returnTypeInSystem = typeVariableSubstitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT);
|
KotlinType returnTypeInSystem = typeVariableSubstitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT);
|
||||||
if (returnTypeInSystem != null) {
|
if (returnTypeInSystem != null) {
|
||||||
constraintSystem.addSupertypeConstraint(expectedType, returnTypeInSystem, FROM_COMPLETER.position());
|
constraintSystem.addSubtypeConstraint(returnTypeInSystem, expectedType, FROM_COMPLETER.position());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
|
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class CallCompleter(
|
|||||||
tracing: TracingStrategy
|
tracing: TracingStrategy
|
||||||
): OverloadResolutionResultsImpl<D> {
|
): OverloadResolutionResultsImpl<D> {
|
||||||
|
|
||||||
val resolvedCall = if (results.isSingleResult()) results.getResultingCall() else null
|
val resolvedCall = if (results.isSingleResult) results.resultingCall else null
|
||||||
|
|
||||||
// for the case 'foo(a)' where 'foo' is a variable, the call 'foo.invoke(a)' shouldn't be completed separately,
|
// for the case 'foo(a)' where 'foo' is a variable, the call 'foo.invoke(a)' shouldn't be completed separately,
|
||||||
// it's completed when the outer (variable as function call) is completed
|
// it's completed when the outer (variable as function call) is completed
|
||||||
@@ -85,13 +85,13 @@ public class CallCompleter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val element = if (resolvedCall is VariableAsFunctionResolvedCall)
|
val element = if (resolvedCall is VariableAsFunctionResolvedCall)
|
||||||
resolvedCall.variableCall.getCall().getCalleeExpression()
|
resolvedCall.variableCall.call.calleeExpression
|
||||||
else
|
else
|
||||||
resolvedCall.getCall().getCalleeExpression()
|
resolvedCall.call.calleeExpression
|
||||||
symbolUsageValidator.validateCall(resolvedCall, resolvedCall.getResultingDescriptor(), context.trace, element!!)
|
symbolUsageValidator.validateCall(resolvedCall, resolvedCall.resultingDescriptor, context.trace, element!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.isSingleResult() && results.getResultingCall().getStatus().isSuccess()) {
|
if (results.isSingleResult && results.resultingCall.status.isSuccess) {
|
||||||
return results.changeStatusToSuccess()
|
return results.changeStatusToSuccess()
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
@@ -103,13 +103,13 @@ public class CallCompleter(
|
|||||||
) {
|
) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val candidates = (if (context.collectAllCandidates) {
|
val candidates = (if (context.collectAllCandidates) {
|
||||||
results.getAllCandidates()!!
|
results.allCandidates!!
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
results.getResultingCalls()
|
results.resultingCalls
|
||||||
}) as Collection<MutableResolvedCall<D>>
|
}) as Collection<MutableResolvedCall<D>>
|
||||||
|
|
||||||
candidates.filter { resolvedCall -> !resolvedCall.isCompleted() }.forEach {
|
candidates.filterNot { resolvedCall -> resolvedCall.isCompleted }.forEach {
|
||||||
resolvedCall ->
|
resolvedCall ->
|
||||||
|
|
||||||
val temporaryBindingTrace = TemporaryBindingTrace.create(context.trace, "Trace to complete a candidate that is not a resulting call")
|
val temporaryBindingTrace = TemporaryBindingTrace.create(context.trace, "Trace to complete a candidate that is not a resulting call")
|
||||||
@@ -123,7 +123,7 @@ public class CallCompleter(
|
|||||||
context: BasicCallResolutionContext,
|
context: BasicCallResolutionContext,
|
||||||
tracing: TracingStrategy
|
tracing: TracingStrategy
|
||||||
) {
|
) {
|
||||||
if (resolvedCall == null || resolvedCall.isCompleted() || resolvedCall.getConstraintSystem() == null) {
|
if (resolvedCall == null || resolvedCall.isCompleted || resolvedCall.constraintSystem == null) {
|
||||||
completeArguments(context, results)
|
completeArguments(context, results)
|
||||||
resolvedCall?.markCallAsCompleted()
|
resolvedCall?.markCallAsCompleted()
|
||||||
return
|
return
|
||||||
@@ -160,14 +160,14 @@ public class CallCompleter(
|
|||||||
updateSystemIfNeeded { builder ->
|
updateSystemIfNeeded { builder ->
|
||||||
val returnTypeInSystem = builder.returnTypeInSystem()
|
val returnTypeInSystem = builder.returnTypeInSystem()
|
||||||
if (returnTypeInSystem != null) {
|
if (returnTypeInSystem != null) {
|
||||||
builder.addSupertypeConstraint(expectedType, returnTypeInSystem, EXPECTED_TYPE_POSITION.position())
|
builder.addSubtypeConstraint(returnTypeInSystem, expectedType, EXPECTED_TYPE_POSITION.position())
|
||||||
builder.build()
|
builder.build()
|
||||||
}
|
}
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val constraintSystemCompleter = trace[CONSTRAINT_SYSTEM_COMPLETER, getCall().getCalleeExpression()]
|
val constraintSystemCompleter = trace[CONSTRAINT_SYSTEM_COMPLETER, call.calleeExpression]
|
||||||
if (constraintSystemCompleter != null) {
|
if (constraintSystemCompleter != null) {
|
||||||
// todo improve error reporting with errors in constraints from completer
|
// todo improve error reporting with errors in constraints from completer
|
||||||
// todo add constraints from completer unconditionally; improve constraints from completer for generic methods
|
// todo add constraints from completer unconditionally; improve constraints from completer for generic methods
|
||||||
@@ -184,7 +184,7 @@ public class CallCompleter(
|
|||||||
updateSystemIfNeeded { builder ->
|
updateSystemIfNeeded { builder ->
|
||||||
val returnTypeInSystem = builder.returnTypeInSystem()
|
val returnTypeInSystem = builder.returnTypeInSystem()
|
||||||
if (returnTypeInSystem != null) {
|
if (returnTypeInSystem != null) {
|
||||||
builder.addSupertypeConstraint(builtIns.getUnitType(), returnTypeInSystem, EXPECTED_TYPE_POSITION.position())
|
builder.addSubtypeConstraint(returnTypeInSystem, builtIns.unitType, EXPECTED_TYPE_POSITION.position())
|
||||||
val system = builder.build()
|
val system = builder.build()
|
||||||
if (system.status.isSuccessful()) system else null
|
if (system.status.isSuccessful()) system else null
|
||||||
}
|
}
|
||||||
@@ -208,8 +208,8 @@ public class CallCompleter(
|
|||||||
val contextWithResolvedCall = CallCandidateResolutionContext.createForCallBeingAnalyzed(this, context, tracing)
|
val contextWithResolvedCall = CallCandidateResolutionContext.createForCallBeingAnalyzed(this, context, tracing)
|
||||||
val valueArgumentsCheckingResult = candidateResolver.checkAllValueArguments(contextWithResolvedCall, RESOLVE_FUNCTION_ARGUMENTS)
|
val valueArgumentsCheckingResult = candidateResolver.checkAllValueArguments(contextWithResolvedCall, RESOLVE_FUNCTION_ARGUMENTS)
|
||||||
|
|
||||||
val status = getStatus()
|
val status = status
|
||||||
if (getConstraintSystem()!!.status.isSuccessful()) {
|
if (constraintSystem!!.status.isSuccessful()) {
|
||||||
if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
|
if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
|
||||||
setStatusToSuccess()
|
setStatusToSuccess()
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ public class CallCompleter(
|
|||||||
val receiverType = if (extensionReceiver.exists() && extensionReceiver is ReceiverValue) extensionReceiver.type else null
|
val receiverType = if (extensionReceiver.exists() && extensionReceiver is ReceiverValue) extensionReceiver.type else null
|
||||||
|
|
||||||
val errorData = InferenceErrorData.create(
|
val errorData = InferenceErrorData.create(
|
||||||
getCandidateDescriptor(), getConstraintSystem()!!, valueArgumentsCheckingResult.argumentTypes,
|
candidateDescriptor, constraintSystem!!, valueArgumentsCheckingResult.argumentTypes,
|
||||||
receiverType, context.expectedType, context.call
|
receiverType, context.expectedType, context.call
|
||||||
)
|
)
|
||||||
tracing.typeInferenceFailed(context.trace, errorData)
|
tracing.typeInferenceFailed(context.trace, errorData)
|
||||||
@@ -236,17 +236,17 @@ public class CallCompleter(
|
|||||||
|
|
||||||
val getArgumentMapping: (ValueArgument) -> ArgumentMapping
|
val getArgumentMapping: (ValueArgument) -> ArgumentMapping
|
||||||
val getDataFlowInfoForArgument: (ValueArgument) -> DataFlowInfo
|
val getDataFlowInfoForArgument: (ValueArgument) -> DataFlowInfo
|
||||||
if (results.isSingleResult()) {
|
if (results.isSingleResult) {
|
||||||
val resolvedCall = results.getResultingCall()
|
val resolvedCall = results.resultingCall
|
||||||
getArgumentMapping = { argument -> resolvedCall.getArgumentMapping(argument) }
|
getArgumentMapping = { argument -> resolvedCall.getArgumentMapping(argument) }
|
||||||
getDataFlowInfoForArgument = {argument -> resolvedCall.getDataFlowInfoForArguments().getInfo(argument) }
|
getDataFlowInfoForArgument = { argument -> resolvedCall.dataFlowInfoForArguments.getInfo(argument) }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
getArgumentMapping = { ArgumentUnmapped }
|
getArgumentMapping = { ArgumentUnmapped }
|
||||||
getDataFlowInfoForArgument = { context.dataFlowInfo }
|
getDataFlowInfoForArgument = { context.dataFlowInfo }
|
||||||
}
|
}
|
||||||
|
|
||||||
for (valueArgument in context.call.getValueArguments()) {
|
for (valueArgument in context.call.valueArguments) {
|
||||||
val argumentMapping = getArgumentMapping(valueArgument!!)
|
val argumentMapping = getArgumentMapping(valueArgument!!)
|
||||||
val expectedType = when (argumentMapping) {
|
val expectedType = when (argumentMapping) {
|
||||||
is ArgumentMatch -> getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument)
|
is ArgumentMatch -> getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument)
|
||||||
@@ -266,18 +266,18 @@ public class CallCompleter(
|
|||||||
val expression = valueArgument.getArgumentExpression() ?: return
|
val expression = valueArgument.getArgumentExpression() ?: return
|
||||||
val deparenthesized = KtPsiUtil.getLastElementDeparenthesized(expression, context.statementFilter) ?: return
|
val deparenthesized = KtPsiUtil.getLastElementDeparenthesized(expression, context.statementFilter) ?: return
|
||||||
|
|
||||||
val recordedType = expression.let { context.trace.getType(it) }
|
val recordedType = context.trace.getType(expression)
|
||||||
var updatedType: KotlinType? = recordedType
|
var updatedType: KotlinType? = recordedType
|
||||||
|
|
||||||
val results = completeCallForArgument(deparenthesized, context)
|
val results = completeCallForArgument(deparenthesized, context)
|
||||||
if (results != null && results.isSingleResult()) {
|
if (results != null && results.isSingleResult) {
|
||||||
val resolvedCall = results.getResultingCall()
|
val resolvedCall = results.resultingCall
|
||||||
updatedType = if (resolvedCall.hasInferredReturnType()) resolvedCall.getResultingDescriptor()?.getReturnType() else null
|
updatedType = if (resolvedCall.hasInferredReturnType()) resolvedCall.resultingDescriptor?.returnType else null
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the cases like 'foo(1)' the type of '1' depends on expected type (it can be Int, Byte, etc.),
|
// For the cases like 'foo(1)' the type of '1' depends on expected type (it can be Int, Byte, etc.),
|
||||||
// so while the expected type is not known, it's IntegerValueType(1), and should be updated when the expected type is known.
|
// so while the expected type is not known, it's IntegerValueType(1), and should be updated when the expected type is known.
|
||||||
if (recordedType != null && !recordedType.getConstructor().isDenotable()) {
|
if (recordedType != null && !recordedType.constructor.isDenotable) {
|
||||||
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression) ?: updatedType
|
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression) ?: updatedType
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,12 +306,10 @@ public class CallCompleter(
|
|||||||
val cachedData = getResolutionResultsCachedData(expression, context) ?: return null
|
val cachedData = getResolutionResultsCachedData(expression, context) ?: return null
|
||||||
val (cachedResolutionResults, cachedContext, tracing) = cachedData
|
val (cachedResolutionResults, cachedContext, tracing) = cachedData
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val cachedResults = cachedResolutionResults as OverloadResolutionResultsImpl<CallableDescriptor>
|
|
||||||
val contextForArgument = cachedContext.replaceBindingTrace(context.trace)
|
val contextForArgument = cachedContext.replaceBindingTrace(context.trace)
|
||||||
.replaceExpectedType(context.expectedType).replaceCollectAllCandidates(false)
|
.replaceExpectedType(context.expectedType).replaceCollectAllCandidates(false)
|
||||||
|
|
||||||
return completeCall(contextForArgument, cachedResults, tracing)
|
return completeCall(contextForArgument, cachedResolutionResults, tracing)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateRecordedTypeForArgument(
|
private fun updateRecordedTypeForArgument(
|
||||||
@@ -327,8 +325,7 @@ public class CallCompleter(
|
|||||||
val deparenthesized = KtPsiUtil.deparenthesizeOnce(expression)
|
val deparenthesized = KtPsiUtil.deparenthesizeOnce(expression)
|
||||||
if (deparenthesized != expression) return deparenthesized
|
if (deparenthesized != expression) return deparenthesized
|
||||||
|
|
||||||
if (expression is KtQualifiedExpression) return expression.getSelectorExpression()
|
return (expression as? KtQualifiedExpression)?.selectorExpression
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val expressions = ArrayList<KtExpression>()
|
val expressions = ArrayList<KtExpression>()
|
||||||
@@ -356,7 +353,7 @@ public class CallCompleter(
|
|||||||
if (expression !is KtSafeQualifiedExpression) return false
|
if (expression !is KtSafeQualifiedExpression) return false
|
||||||
|
|
||||||
//If a receiver type is not null, then this safe expression is useless, and we don't need to make the result type nullable.
|
//If a receiver type is not null, then this safe expression is useless, and we don't need to make the result type nullable.
|
||||||
val expressionType = trace.getType(expression.getReceiverExpression())
|
val expressionType = trace.getType(expression.receiverExpression)
|
||||||
return expressionType != null && TypeUtils.isNullableType(expressionType)
|
return expressionType != null && TypeUtils.isNullableType(expressionType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,15 +72,6 @@ interface ConstraintSystem {
|
|||||||
*/
|
*/
|
||||||
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.
|
|
||||||
* 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)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each call for which type variables were registered, a type substitutor is stored in this map which maps
|
* For each call for which type variables were registered, a type substitutor is stored in this map which maps
|
||||||
* type parameter descriptors of the candidate descriptor of that call -> type variables of the system.
|
* type parameter descriptors of the candidate descriptor of that call -> type variables of the system.
|
||||||
|
|||||||
-4
@@ -107,10 +107,6 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
internal fun getNestedTypeVariables(type: KotlinType): List<TypeVariable> =
|
internal fun getNestedTypeVariables(type: KotlinType): List<TypeVariable> =
|
||||||
type.getNestedTypeParameters().map { getMyTypeVariable(it) }.filterNotNull()
|
type.getNestedTypeParameters().map { getMyTypeVariable(it) }.filterNotNull()
|
||||||
|
|
||||||
override fun addSupertypeConstraint(constrainingType: KotlinType, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
|
||||||
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) {
|
||||||
addConstraint(SUB_TYPE, constrainingType, subjectType, ConstraintContext(constraintPosition, initial = true))
|
addConstraint(SUB_TYPE, constrainingType, subjectType, ConstraintContext(constraintPosition, initial = true))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user