Initial OverloadingConflictResolver abstraction from KotlinTypes

This commit is contained in:
Simon Ogorodnik
2019-04-03 16:20:57 +03:00
parent 9a1678728d
commit 8e595f015e
17 changed files with 122 additions and 57 deletions
@@ -16,30 +16,29 @@
package org.jetbrains.kotlin.resolve.jvm
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.asFlexibleType
import org.jetbrains.kotlin.types.isFlexible
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate
object JvmTypeSpecificityComparator : TypeSpecificityComparator {
class JvmTypeSpecificityComparator(val context: TypeSystemInferenceExtensionContextDelegate) : TypeSpecificityComparator {
override fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType): Boolean {
if (!specific.isFlexible() || general.isFlexible()) return false
override fun isDefinitelyLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean = with(context) {
val simpleGeneral = general.asSimpleType()
if (!specific.isFlexible() || simpleGeneral == null) return false
// general is inflexible
val flexibility = specific.asFlexibleType()
val flexibility = specific.asFlexibleType()!!
// For primitive types we have to take care of the case when there are two overloaded methods like
// foo(int) and foo(Integer)
// if we do not discriminate one of them, any call to foo(kotlin.Int) will result in overload resolution ambiguity
// so, for such cases, we discriminate Integer in favour of int
if (!KotlinBuiltIns.isPrimitiveType(general) || !KotlinBuiltIns.isPrimitiveType(flexibility.lowerBound)) {
if (!simpleGeneral.isPrimitiveType() || !flexibility.lowerBound().isPrimitiveType()) {
return false
}
// Int? >< Int!
if (general.isMarkedNullable) return false
if (simpleGeneral.isMarkedNullable()) return false
// Int! lessSpecific Int
return true
}
@@ -96,7 +96,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
container.useImpl<InlinePlatformCompatibilityChecker>()
container.useImpl<JvmModuleAccessibilityChecker>()
container.useImpl<JvmModuleAccessibilityChecker.ClassifierUsage>()
container.useInstance(JvmTypeSpecificityComparator)
container.useImpl<JvmTypeSpecificityComparator>()
container.useImpl<JvmDefaultSuperCallChecker>()
container.useImpl<JvmSamConversionTransformer>()
container.useInstance(FunctionWithBigAritySupport.LANGUAGE_VERSION_DEPENDENT)
@@ -27,9 +27,10 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
object OverloadabilitySpecificityCallbacks : SpecificityComparisonCallbacks {
override fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean =
override fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean =
false
}
@@ -34,11 +34,17 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks
import org.jetbrains.kotlin.types.checker.requireOrDescribe
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.defaultProjections
import org.jetbrains.kotlin.types.typeUtil.isDefaultBound
import org.jetbrains.kotlin.utils.addToStdlib.cast
import java.lang.IllegalArgumentException
import java.lang.IllegalStateException
import java.util.*
@@ -426,13 +432,18 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
companion object {
fun forSpecificity(): SimpleConstraintSystem = object : ConstraintSystemBuilderImpl(Mode.SPECIFICITY), SimpleConstraintSystem {
override val context: TypeSystemInferenceExtensionContext
get() = SimpleClassicTypeSystemContext
var counter = 0
override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>) =
registerTypeVariables(CallHandle.NONE, typeParameters)
override fun registerTypeVariables(typeParameters: Collection<TypeParameterMarker>) =
registerTypeVariables(CallHandle.NONE, typeParameters.cast())
override fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType) =
override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker) {
requireOrDescribe(subType is UnwrappedType, subType)
requireOrDescribe(superType is UnwrappedType, superType)
addSubtypeConstraint(subType, superType, ConstraintPositionKind.VALUE_PARAMETER_POSITION.position(counter++))
}
override fun hasContradiction(): Boolean {
fixVariables()
@@ -25,17 +25,23 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallab
import org.jetbrains.kotlin.resolve.calls.inference.substitute
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
import org.jetbrains.kotlin.types.checker.requireOrDescribe
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns) : SimpleConstraintSystem {
val system = NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns))
val csBuilder: ConstraintSystemBuilder =
NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns)).getBuilder()
system.getBuilder()
override fun registerTypeVariables(typeParameters: Collection<TypeParameterMarker>): TypeSubstitutor {
override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>): TypeSubstitutor {
val substitutionMap = typeParameters.associate {
requireOrDescribe(it is TypeParameterDescriptor, it)
val variable = TypeVariableFromCallableDescriptor(it)
csBuilder.registerVariable(variable)
@@ -43,6 +49,7 @@ class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, builtIn
}
val substitutor = TypeConstructorSubstitution.createByConstructorsMap(substitutionMap).buildSubstitutor()
for (typeParameter in typeParameters) {
requireOrDescribe(typeParameter is TypeParameterDescriptor, typeParameter)
for (upperBound in typeParameter.upperBounds) {
addSubtypeConstraint(substitutor.substitute(typeParameter.defaultType), substitutor.substitute(upperBound.unwrap()))
}
@@ -50,7 +57,9 @@ class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, builtIn
return substitutor
}
override fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType) {
override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker) {
require(subType is UnwrappedType)
require(superType is UnwrappedType)
csBuilder.addSubtypeConstraint(
subType,
superType,
@@ -61,4 +70,7 @@ class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, builtIn
override fun hasContradiction() = csBuilder.hasContradiction
override val captureFromArgument get() = true
override val context: TypeSystemInferenceExtensionContext
get() = system
}
@@ -18,30 +18,31 @@ package org.jetbrains.kotlin.resolve.calls.results
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.checker.captureFromExpression
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
interface SpecificityComparisonCallbacks {
fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean
fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean
}
interface TypeSpecificityComparator {
fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType): Boolean
fun isDefinitelyLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean
object NONE : TypeSpecificityComparator {
override fun isDefinitelyLessSpecific(specific: KotlinType, general: KotlinType) = false
override fun isDefinitelyLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker) = false
}
}
class FlatSignature<out T> private constructor(
class FlatSignature<out T> constructor(
val origin: T,
val typeParameters: Collection<TypeParameterDescriptor>,
val valueParameterTypes: List<KotlinType?>,
val typeParameters: Collection<TypeParameterMarker>,
val valueParameterTypes: List<KotlinTypeMarker?>,
val hasExtensionReceiver: Boolean,
val hasVarargs: Boolean,
val numDefaults: Int,
@@ -113,12 +114,14 @@ class FlatSignature<out T> private constructor(
interface SimpleConstraintSystem {
fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>): TypeSubstitutor
fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType)
fun registerTypeVariables(typeParameters: Collection<TypeParameterMarker>): TypeSubstitutor
fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker)
fun hasContradiction(): Boolean
// todo hack for migration
val captureFromArgument get() = false
val context: TypeSystemInferenceExtensionContext
}
fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
@@ -131,7 +134,6 @@ fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
if (specific.valueParameterTypes.size != general.valueParameterTypes.size) return false
val typeParameters = general.typeParameters
val typeSubstitutor = registerTypeVariables(typeParameters)
for ((specificType, generalType) in specific.valueParameterTypes.zip(general.valueParameterTypes)) {
if (specificType == null || generalType == null) continue
@@ -140,13 +142,17 @@ fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
return false
}
if (typeParameters.isEmpty() || !TypeUtils.dependsOnTypeParameters(generalType, typeParameters)) {
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(specificType, generalType)) {
if (typeParameters.isEmpty() /*|| !TypeUtils.dependsOnTypeParameters(generalType, typeParameters)*/) {
if (!AbstractTypeChecker.isSubtypeOf(context, specificType, generalType)) {
if (!callbacks.isNonSubtypeNotLessSpecific(specificType, generalType)) {
return false
}
}
} else {
val typeSubstitutor = registerTypeVariables(typeParameters)
require(generalType is KotlinType) { TODO("not supported") }
require(specificType is KotlinType) { TODO("not supported") }
val substitutedGeneralType = typeSubstitutor.safeSubstitute(generalType, Variance.INVARIANT)
/**
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.requireOrDescribe
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import java.util.*
open class OverloadingConflictResolver<C : Any>(
@@ -284,7 +286,10 @@ open class OverloadingConflictResolver<C : Any>(
}
private val SpecificityComparisonWithNumerics = object : SpecificityComparisonCallbacks {
override fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean {
override fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean {
requireOrDescribe(specific is KotlinType, specific)
requireOrDescribe(general is KotlinType, general)
val _double = builtIns.doubleType
val _float = builtIns.floatType