Don't use originalToVariableSubstitutor in supertype constraints
This commit is contained in:
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.*;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter;
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeVariableKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||||
@@ -36,9 +37,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
import org.jetbrains.kotlin.resolve.validation.OperatorValidator;
|
import org.jetbrains.kotlin.resolve.validation.OperatorValidator;
|
||||||
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator;
|
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator;
|
||||||
import org.jetbrains.kotlin.types.DeferredType;
|
import org.jetbrains.kotlin.types.*;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
||||||
@@ -369,7 +368,13 @@ 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)) {
|
||||||
constraintSystem.addSupertypeConstraint(expectedType, returnTypeOfGetMethod, FROM_COMPLETER.position());
|
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);
|
||||||
|
if (returnTypeInSystem != null) {
|
||||||
|
constraintSystem.addSupertypeConstraint(expectedType, returnTypeInSystem, FROM_COMPLETER.position());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addConstraintForThisValue(constraintSystem, descriptor);
|
addConstraintForThisValue(constraintSystem, descriptor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.filterConstraintsOut
|
import org.jetbrains.kotlin.resolve.calls.inference.filterConstraintsOut
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||||
@@ -44,6 +45,7 @@ import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
|||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -139,6 +141,14 @@ public class CallCompleter(
|
|||||||
expectedType: KotlinType,
|
expectedType: KotlinType,
|
||||||
trace: BindingTrace
|
trace: BindingTrace
|
||||||
) {
|
) {
|
||||||
|
val returnType = candidateDescriptor.returnType
|
||||||
|
|
||||||
|
fun ConstraintSystem.Builder.returnTypeInSystem(): KotlinType? =
|
||||||
|
returnType?.let {
|
||||||
|
val substitutor = typeVariableSubstitutors[call.toHandle()] ?: error("No substitutor for call: $call")
|
||||||
|
substitutor.substitute(it, Variance.INVARIANT)
|
||||||
|
}
|
||||||
|
|
||||||
fun updateSystemIfNeeded(buildSystemWithAdditionalConstraints: (ConstraintSystem.Builder) -> ConstraintSystem?) {
|
fun updateSystemIfNeeded(buildSystemWithAdditionalConstraints: (ConstraintSystem.Builder) -> ConstraintSystem?) {
|
||||||
val system = buildSystemWithAdditionalConstraints(constraintSystem!!.toBuilder())
|
val system = buildSystemWithAdditionalConstraints(constraintSystem!!.toBuilder())
|
||||||
if (system != null) {
|
if (system != null) {
|
||||||
@@ -146,11 +156,14 @@ public class CallCompleter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val returnType = getCandidateDescriptor().getReturnType()
|
|
||||||
if (returnType != null && !TypeUtils.noExpectedType(expectedType)) {
|
if (returnType != null && !TypeUtils.noExpectedType(expectedType)) {
|
||||||
updateSystemIfNeeded { builder ->
|
updateSystemIfNeeded { builder ->
|
||||||
builder.addSupertypeConstraint(expectedType, returnType, EXPECTED_TYPE_POSITION.position())
|
val returnTypeInSystem = builder.returnTypeInSystem()
|
||||||
builder.build()
|
if (returnTypeInSystem != null) {
|
||||||
|
builder.addSupertypeConstraint(expectedType, returnTypeInSystem, EXPECTED_TYPE_POSITION.position())
|
||||||
|
builder.build()
|
||||||
|
}
|
||||||
|
else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,9 +182,13 @@ public class CallCompleter(
|
|||||||
|
|
||||||
if (returnType != null && expectedType === TypeUtils.UNIT_EXPECTED_TYPE) {
|
if (returnType != null && expectedType === TypeUtils.UNIT_EXPECTED_TYPE) {
|
||||||
updateSystemIfNeeded { builder ->
|
updateSystemIfNeeded { builder ->
|
||||||
builder.addSupertypeConstraint(builtIns.getUnitType(), returnType, EXPECTED_TYPE_POSITION.position())
|
val returnTypeInSystem = builder.returnTypeInSystem()
|
||||||
val system = builder.build()
|
if (returnTypeInSystem != null) {
|
||||||
if (system.status.isSuccessful()) system else null
|
builder.addSupertypeConstraint(builtIns.getUnitType(), returnTypeInSystem, EXPECTED_TYPE_POSITION.position())
|
||||||
|
val system = builder.build()
|
||||||
|
if (system.status.isSuccessful()) system else null
|
||||||
|
}
|
||||||
|
else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -86,7 +86,14 @@ interface ConstraintSystem {
|
|||||||
* For example, for `fun <T> create(): T` to infer `T` in invocation `val i: Int = create()`
|
* 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.
|
* 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 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
|
||||||
|
* type parameter descriptors of the candidate descriptor of that call -> type variables of the system.
|
||||||
|
* Those are the same substitutors that are returned by [registerTypeVariables] at the time of variable registration.
|
||||||
|
*/
|
||||||
|
val typeVariableSubstitutors: Map<CallHandle, TypeSubstitutor>
|
||||||
|
|
||||||
fun fixVariables()
|
fun fixVariables()
|
||||||
|
|
||||||
|
|||||||
+18
-7
@@ -53,6 +53,8 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
internal val initialConstraints = ArrayList<Constraint>()
|
internal val initialConstraints = ArrayList<Constraint>()
|
||||||
internal val descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeVariable>()
|
internal val descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeVariable>()
|
||||||
|
|
||||||
|
override val typeVariableSubstitutors = LinkedHashMap<CallHandle, TypeSubstitutor>()
|
||||||
|
|
||||||
private val descriptorToVariableSubstitutor: TypeSubstitutor by lazy {
|
private val descriptorToVariableSubstitutor: TypeSubstitutor by lazy {
|
||||||
TypeSubstitutor.create(object : TypeConstructorSubstitution() {
|
TypeSubstitutor.create(object : TypeConstructorSubstitution() {
|
||||||
override fun get(key: TypeConstructor): TypeProjection? {
|
override fun get(key: TypeConstructor): TypeProjection? {
|
||||||
@@ -64,10 +66,18 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
typeVariableSubstitutors[call] = substitutor
|
||||||
|
return substitutor
|
||||||
|
}
|
||||||
|
|
||||||
override fun registerTypeVariables(
|
override fun registerTypeVariables(
|
||||||
call: CallHandle, typeParameters: Collection<TypeParameterDescriptor>, external: Boolean
|
call: CallHandle, typeParameters: Collection<TypeParameterDescriptor>, external: Boolean
|
||||||
): TypeSubstitutor {
|
): TypeSubstitutor {
|
||||||
if (typeParameters.isEmpty()) return TypeSubstitutor.EMPTY
|
if (typeParameters.isEmpty()) return storeSubstitutor(call, TypeSubstitutor.EMPTY)
|
||||||
|
|
||||||
val typeVariables = if (external) {
|
val typeVariables = if (external) {
|
||||||
typeParameters.map {
|
typeParameters.map {
|
||||||
@@ -98,9 +108,9 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeSubstitutor.create(TypeConstructorSubstitution.createByParametersMap(
|
return storeSubstitutor(call, TypeSubstitutor.create(TypeConstructorSubstitution.createByParametersMap(
|
||||||
typeParameters.zip(typeVariables.map { it.type }.defaultProjections()).toMap()
|
typeParameters.zip(typeVariables.map { it.type }.defaultProjections()).toMap()
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.isProper() = !TypeUtils.containsSpecialType(this) {
|
private fun KotlinType.isProper() = !TypeUtils.containsSpecialType(this) {
|
||||||
@@ -110,9 +120,8 @@ 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) {
|
override fun addSupertypeConstraint(constrainingType: KotlinType, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
||||||
val newSubjectType = descriptorToVariableSubstitutor.substitute(subjectType, Variance.INVARIANT)
|
addConstraint(SUB_TYPE, subjectType, constrainingType, ConstraintContext(constraintPosition, initial = true))
|
||||||
addConstraint(SUB_TYPE, newSubjectType, constrainingType, ConstraintContext(constraintPosition, initial = true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
||||||
@@ -378,7 +387,9 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun build(): ConstraintSystem {
|
override fun build(): ConstraintSystem {
|
||||||
return ConstraintSystemImpl(allTypeParameterBounds, usedInBounds, errors, initialConstraints, descriptorToVariable)
|
return ConstraintSystemImpl(
|
||||||
|
allTypeParameterBounds, usedInBounds, errors, initialConstraints, descriptorToVariable, typeVariableSubstitutors
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -38,7 +38,8 @@ 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 descriptorToVariable: Map<TypeParameterDescriptor, TypeVariable>,
|
||||||
|
private val typeVariableSubstitutors: Map<CallHandle, TypeSubstitutor>
|
||||||
) : ConstraintSystem {
|
) : ConstraintSystem {
|
||||||
private val localTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl>
|
private val localTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl>
|
||||||
get() = allTypeParameterBounds.filterNot { it.key.isExternal }
|
get() = allTypeParameterBounds.filterNot { it.key.isExternal }
|
||||||
@@ -167,6 +168,7 @@ internal class ConstraintSystemImpl(
|
|||||||
|
|
||||||
result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
|
result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
|
||||||
result.descriptorToVariable.putAll(descriptorToVariable)
|
result.descriptorToVariable.putAll(descriptorToVariable)
|
||||||
|
result.typeVariableSubstitutors.putAll(typeVariableSubstitutors)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -99,9 +99,10 @@ abstract public class AbstractConstraintSystemTest() : KotlinLiteFixture() {
|
|||||||
val context = ConstraintContext(SPECIAL.position(), initial = true)
|
val context = ConstraintContext(SPECIAL.position(), initial = true)
|
||||||
when (constraint.kind) {
|
when (constraint.kind) {
|
||||||
MyConstraintKind.SUBTYPE -> builder.addSubtypeConstraint(firstType, secondType, context.position)
|
MyConstraintKind.SUBTYPE -> builder.addSubtypeConstraint(firstType, secondType, context.position)
|
||||||
MyConstraintKind.SUPERTYPE -> builder.addSupertypeConstraint(firstType, secondType, context.position)
|
MyConstraintKind.SUPERTYPE -> builder.addSubtypeConstraint(secondType, firstType, context.position)
|
||||||
MyConstraintKind.EQUAL -> builder.addConstraint(
|
MyConstraintKind.EQUAL -> builder.addConstraint(
|
||||||
ConstraintSystemBuilderImpl.ConstraintKind.EQUAL, firstType, secondType, context)
|
ConstraintSystemBuilderImpl.ConstraintKind.EQUAL, firstType, secondType, context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user