Introduce SimpleConstraintSystem for OverloadChecker and OverloadingConflictResolver

This commit is contained in:
Stanislav Erokhin
2016-08-23 18:31:10 +03:00
parent 5ad0e4e9b8
commit f31493f80f
4 changed files with 40 additions and 23 deletions
@@ -21,7 +21,11 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.results.* import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
import org.jetbrains.kotlin.resolve.calls.results.SpecificityComparisonCallbacks
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.results.isSignatureNotLessSpecific
import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition
@@ -63,8 +67,8 @@ class OverloadChecker(val specificityComparator: TypeSpecificityComparator) {
val aSignature = FlatSignature.createFromCallableDescriptor(a) val aSignature = FlatSignature.createFromCallableDescriptor(a)
val bSignature = FlatSignature.createFromCallableDescriptor(b) val bSignature = FlatSignature.createFromCallableDescriptor(b)
val aIsNotLessSpecificThanB = isSignatureNotLessSpecific(aSignature, bSignature, OverloadabilitySpecificityCallbacks, specificityComparator) val aIsNotLessSpecificThanB = ConstraintSystemBuilderImpl.forSpecificity().isSignatureNotLessSpecific (aSignature, bSignature, OverloadabilitySpecificityCallbacks, specificityComparator)
val bIsNotLessSpecificThanA = isSignatureNotLessSpecific(bSignature, aSignature, OverloadabilitySpecificityCallbacks, specificityComparator) val bIsNotLessSpecificThanA = ConstraintSystemBuilderImpl.forSpecificity().isSignatureNotLessSpecific(bSignature, aSignature, OverloadabilitySpecificityCallbacks, specificityComparator)
return !(aIsNotLessSpecificThanB && bIsNotLessSpecificThanA) return !(aIsNotLessSpecificThanB && bIsNotLessSpecificThanA)
} }
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.*
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
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.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.resolve.calls.util.createFunctionType import org.jetbrains.kotlin.resolve.calls.util.createFunctionType
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
@@ -38,7 +39,7 @@ import org.jetbrains.kotlin.types.typeUtil.defaultProjections
import org.jetbrains.kotlin.types.typeUtil.isDefaultBound import org.jetbrains.kotlin.types.typeUtil.isDefaultBound
import java.util.* import java.util.*
class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystemBuilderImpl.Mode.INFERENCE) : ConstraintSystem.Builder { open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystemBuilderImpl.Mode.INFERENCE) : ConstraintSystem.Builder {
enum class Mode { enum class Mode {
INFERENCE, INFERENCE,
SPECIFICITY SPECIFICITY
@@ -409,7 +410,20 @@ class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystemBuild
} }
companion object { companion object {
fun forSpecificity() = ConstraintSystemBuilderImpl(Mode.SPECIFICITY) fun forSpecificity(): SimpleConstraintSystem = object : ConstraintSystemBuilderImpl(Mode.SPECIFICITY), SimpleConstraintSystem {
var counter = 0
override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>) =
registerTypeVariables(CallHandle.NONE, typeParameters)
override fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType) =
addSubtypeConstraint(subType, superType, ConstraintPositionKind.VALUE_PARAMETER_POSITION.position(counter++))
override fun hasContradiction(): Boolean {
fixVariables()
return build().status.hasContradiction()
}
}
} }
} }
@@ -17,21 +17,17 @@
package org.jetbrains.kotlin.resolve.calls.results package org.jetbrains.kotlin.resolve.calls.results
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.valueParameterPosition
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature.Companion.argumentValueType import org.jetbrains.kotlin.resolve.calls.results.FlatSignature.Companion.argumentValueType
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature.Companion.extensionReceiverTypeOrEmpty import org.jetbrains.kotlin.resolve.calls.results.FlatSignature.Companion.extensionReceiverTypeOrEmpty
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import java.util.* import java.util.*
@@ -47,21 +43,24 @@ interface TypeSpecificityComparator {
} }
} }
fun <T> isSignatureNotLessSpecific( interface SimpleConstraintSystem {
fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>): TypeSubstitutor
fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType)
fun hasContradiction(): Boolean
}
fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
specific: FlatSignature<T>, specific: FlatSignature<T>,
general: FlatSignature<T>, general: FlatSignature<T>,
callbacks: SpecificityComparisonCallbacks, callbacks: SpecificityComparisonCallbacks,
specificityComparator: TypeSpecificityComparator, specificityComparator: TypeSpecificityComparator
callHandle: CallHandle = CallHandle.NONE
): Boolean { ): Boolean {
if (specific.hasExtensionReceiver != general.hasExtensionReceiver) return false if (specific.hasExtensionReceiver != general.hasExtensionReceiver) return false
if (specific.valueParameterTypes.size != general.valueParameterTypes.size) return false if (specific.valueParameterTypes.size != general.valueParameterTypes.size) return false
val typeParameters = general.typeParameters val typeParameters = general.typeParameters
val constraintSystemBuilder: ConstraintSystem.Builder = ConstraintSystemBuilderImpl.forSpecificity() val typeSubstitutor = registerTypeVariables(typeParameters)
val typeSubstitutor = constraintSystemBuilder.registerTypeVariables(callHandle, typeParameters)
var numConstraints = 0
for ((specificType, generalType) in specific.valueParameterTypes.zip(general.valueParameterTypes)) { for ((specificType, generalType) in specific.valueParameterTypes.zip(general.valueParameterTypes)) {
if (specificType == null || generalType == null) continue if (specificType == null || generalType == null) continue
@@ -78,13 +77,11 @@ fun <T> isSignatureNotLessSpecific(
} }
else { else {
val substitutedGeneralType = typeSubstitutor.safeSubstitute(generalType, Variance.INVARIANT) val substitutedGeneralType = typeSubstitutor.safeSubstitute(generalType, Variance.INVARIANT)
constraintSystemBuilder.addSubtypeConstraint(specificType, substitutedGeneralType, valueParameterPosition(numConstraints++)) addSubtypeConstraint(specificType.unwrap(), substitutedGeneralType.unwrap())
} }
} }
constraintSystemBuilder.fixVariables() return !hasContradiction()
val constraintSystem = constraintSystemBuilder.build()
return !constraintSystem.status.hasContradiction()
} }
@@ -123,6 +120,7 @@ fun createOverloadingConflictResolver(
builtIns, builtIns,
specificityComparator, specificityComparator,
MutableResolvedCall<*>::getResultingDescriptor, MutableResolvedCall<*>::getResultingDescriptor,
ConstraintSystemBuilderImpl.Companion::forSpecificity,
MutableResolvedCall<*>::createFlatSignature, MutableResolvedCall<*>::createFlatSignature,
{ (it as? VariableAsFunctionResolvedCallImpl)?.variableCall }, { (it as? VariableAsFunctionResolvedCallImpl)?.variableCall },
{ DescriptorToSourceUtils.descriptorToDeclaration(it) != null} { DescriptorToSourceUtils.descriptorToDeclaration(it) != null}
@@ -34,6 +34,7 @@ class OverloadingConflictResolver<C : Any>(
private val builtIns: KotlinBuiltIns, private val builtIns: KotlinBuiltIns,
private val specificityComparator: TypeSpecificityComparator, private val specificityComparator: TypeSpecificityComparator,
private val getResultingDescriptor: (C) -> CallableDescriptor, private val getResultingDescriptor: (C) -> CallableDescriptor,
private val createEmptyConstraintSystem: () -> SimpleConstraintSystem,
private val createFlatSignature: (C) -> FlatSignature<C>, private val createFlatSignature: (C) -> FlatSignature<C>,
private val getVariableCandidates: (C) -> C?, // vor variable WithInvoke private val getVariableCandidates: (C) -> C?, // vor variable WithInvoke
private val isFromSources: (CallableDescriptor) -> Boolean private val isFromSources: (CallableDescriptor) -> Boolean
@@ -235,7 +236,7 @@ class OverloadingConflictResolver<C : Any>(
if (isGeneric1 && isGeneric2) return false if (isGeneric1 && isGeneric2) return false
} }
return isSignatureNotLessSpecific(call1, call2, SpecificityComparisonWithNumerics, specificityComparator) return createEmptyConstraintSystem().isSignatureNotLessSpecific(call1, call2, SpecificityComparisonWithNumerics, specificityComparator)
} }
private val SpecificityComparisonWithNumerics = object : SpecificityComparisonCallbacks { private val SpecificityComparisonWithNumerics = object : SpecificityComparisonCallbacks {
@@ -321,7 +322,7 @@ class OverloadingConflictResolver<C : Any>(
val fSignature = FlatSignature.createFromCallableDescriptor(f) val fSignature = FlatSignature.createFromCallableDescriptor(f)
val gSignature = FlatSignature.createFromCallableDescriptor(g) val gSignature = FlatSignature.createFromCallableDescriptor(g)
return isSignatureNotLessSpecific(fSignature, gSignature, SpecificityComparisonWithNumerics, specificityComparator) return createEmptyConstraintSystem().isSignatureNotLessSpecific(fSignature, gSignature, SpecificityComparisonWithNumerics, specificityComparator)
} }
private fun isNotLessSpecificCallableReference(f: CallableDescriptor, g: CallableDescriptor): Boolean = private fun isNotLessSpecificCallableReference(f: CallableDescriptor, g: CallableDescriptor): Boolean =