Abstract NewInference & related from KotlinType
Cleanup TypeConstructors & KotlinTypes in VariableFixationFinder Cleanup TypeConstructors & KotlinTypes in TypeVariableDirectionCalculator Cleanup KotlinTypes in TypeCheckerContext for ConstraintSystem Cleanup KotlinTypes in NewCommonSuperTypeCalculator Cleanup KotlinTypes in TypeApproximator Cleanup type substitution Cleanup NewTypeVariable Cleanup StubType Cleanup TypeCheckerContext creation, extract common supertype context Provide TypeSystemInferenceExtensionContext via dependency injection
This commit is contained in:
@@ -333,6 +333,23 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext {
|
||||
symbol is FirTypeParameterSymbol
|
||||
}
|
||||
|
||||
override fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.isStubType(): Boolean {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -359,4 +376,8 @@ class ConeTypeCheckerContext(override val isErrorTypeEqualsToAnything: Boolean,
|
||||
get() = false
|
||||
|
||||
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return super<ConeTypeContext>.prepareType(type)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbacksImpl
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
||||
@@ -72,6 +73,7 @@ private fun StorageComponentContainer.configurePlatformIndependentComponents() {
|
||||
useImpl<ExperimentalUsageChecker>()
|
||||
useImpl<ExperimentalUsageChecker.Overrides>()
|
||||
useImpl<ExperimentalUsageChecker.ClassifierUsage>()
|
||||
useImpl<ClassicTypeSystemContextForCS>()
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.configureModule(
|
||||
|
||||
+10
-5
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.constants.CompileTimeConstantChecker
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class DiagnosticReporterByTrackingStrategy(
|
||||
@@ -212,19 +213,19 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
val expression = it.psiExpression ?: return
|
||||
val deparenthesized = KtPsiUtil.safeDeparenthesize(expression)
|
||||
if (reportConstantTypeMismatch(constraintError, deparenthesized)) return
|
||||
trace.report(Errors.TYPE_MISMATCH.on(deparenthesized, constraintError.upperType, constraintError.lowerType))
|
||||
trace.report(Errors.TYPE_MISMATCH.on(deparenthesized, constraintError.upperKotlinType, constraintError.lowerKotlinType))
|
||||
}
|
||||
|
||||
(position as? ExpectedTypeConstraintPosition)?.let {
|
||||
val call = it.topLevelCall.psiKotlinCall.psiCall.callElement.safeAs<KtExpression>()
|
||||
reportIfNonNull(call) {
|
||||
trace.report(Errors.TYPE_MISMATCH.on(it, constraintError.upperType, constraintError.lowerType))
|
||||
trace.report(Errors.TYPE_MISMATCH.on(it, constraintError.upperKotlinType, constraintError.lowerKotlinType))
|
||||
}
|
||||
}
|
||||
|
||||
(position as? ExplicitTypeParameterConstraintPosition)?.let {
|
||||
val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference
|
||||
trace.report(UPPER_BOUND_VIOLATED.on(typeArgumentReference, constraintError.upperType, constraintError.lowerType))
|
||||
trace.report(UPPER_BOUND_VIOLATED.on(typeArgumentReference, constraintError.upperKotlinType, constraintError.lowerKotlinType))
|
||||
}
|
||||
}
|
||||
CapturedTypeFromSubtyping::class.java -> {
|
||||
@@ -247,10 +248,14 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
val module = context.scope.ownerDescriptor.module
|
||||
val constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, trace, context.expectedType)
|
||||
val hasConstantTypeError = CompileTimeConstantChecker(context, module, true)
|
||||
.checkConstantExpressionType(constantValue, expression, constraintError.upperType)
|
||||
.checkConstantExpressionType(constantValue, expression, constraintError.upperKotlinType)
|
||||
if (hasConstantTypeError) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val NewConstraintError.upperKotlinType get() = upperType as KotlinType
|
||||
val NewConstraintError.lowerKotlinType get() = lowerType as KotlinType
|
||||
+7
-5
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.components.CompletedCallInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
|
||||
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class CoroutineInferenceSession(
|
||||
psiCallResolver: PSICallResolver,
|
||||
@@ -88,7 +90,7 @@ class CoroutineInferenceSession(
|
||||
|
||||
updateCalls(lambda, commonSystem)
|
||||
|
||||
return commonSystem.fixedTypeVariables
|
||||
return commonSystem.fixedTypeVariables.cast() // TODO: SUB
|
||||
}
|
||||
|
||||
private fun createNonFixedTypeToVariableSubstitutor(): NewTypeSubstitutorByConstructorMap {
|
||||
@@ -117,8 +119,8 @@ class CoroutineInferenceSession(
|
||||
val callSubstitutor = storage.buildResultingSubstitutor() // substitutor only for fixed variables
|
||||
|
||||
for (initialConstraint in storage.initialConstraints) {
|
||||
val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a))
|
||||
val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b))
|
||||
val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB
|
||||
val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)) // TODO: SUB
|
||||
|
||||
if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue
|
||||
|
||||
@@ -183,9 +185,9 @@ class CoroutineInferenceSession(
|
||||
nonFixedTypesToResult: Map<TypeConstructor, UnwrappedType>
|
||||
) {
|
||||
val resultingCallSubstitutor = completedCall.callResolutionResult.constraintSystem.fixedTypeVariables.entries
|
||||
.associate { it.key to nonFixedTypesToResultSubstitutor.safeSubstitute(it.value) }
|
||||
.associate { it.key to nonFixedTypesToResultSubstitutor.safeSubstitute(it.value as UnwrappedType) } // TODO: SUB
|
||||
|
||||
val resultingSubstitutor = NewTypeSubstitutorByConstructorMap(resultingCallSubstitutor + nonFixedTypesToResult)
|
||||
val resultingSubstitutor = NewTypeSubstitutorByConstructorMap((resultingCallSubstitutor + nonFixedTypesToResult).cast()) // TODO: SUB
|
||||
|
||||
val atomCompleter = createResolvedAtomCompleter(resultingSubstitutor, completedCall.context)
|
||||
val resultCallAtom = completedCall.callResolutionResult.resultCallAtom
|
||||
|
||||
+3
-1
@@ -665,7 +665,9 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
|
||||
typeArguments = resolvedCallAtom.substitutor.freshVariables.map {
|
||||
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
|
||||
TypeApproximator().approximateToSuperType(substituted, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) ?: substituted
|
||||
TypeApproximator(substituted.constructor.builtIns)
|
||||
.approximateToSuperType(substituted, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation)
|
||||
?: substituted
|
||||
}
|
||||
|
||||
calculateExpedtedTypeForSamConvertedArgumentMap(substitutor)
|
||||
|
||||
+1
-1
@@ -134,7 +134,7 @@ class ResolvedAtomCompleter(
|
||||
}
|
||||
|
||||
val approximatedReturnType =
|
||||
TypeApproximator().approximateDeclarationType(
|
||||
TypeApproximator(builtIns).approximateDeclarationType(
|
||||
returnType,
|
||||
local = true,
|
||||
languageVersionSettings = topLevelCallContext.languageVersionSettings
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ internal val jvmCoercionToUnitPhase = makeIrFilePhase(
|
||||
class JvmCoercionToUnitPatcher(val context: JvmBackendContext) :
|
||||
InsertImplicitCasts(
|
||||
context.builtIns, context.irBuiltIns,
|
||||
TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings),
|
||||
TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings, context.builtIns),
|
||||
JvmGeneratorExtensions.samConversion
|
||||
),
|
||||
FileLoweringPass {
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ class GeneratorContext(
|
||||
) : IrGeneratorContext() {
|
||||
|
||||
val constantValueGenerator: ConstantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
|
||||
val typeTranslator: TypeTranslator = TypeTranslator(symbolTable, languageVersionSettings)
|
||||
val typeTranslator: TypeTranslator = TypeTranslator(symbolTable, languageVersionSettings, builtIns = moduleDescriptor.builtIns)
|
||||
|
||||
init {
|
||||
typeTranslator.constantValueGenerator = constantValueGenerator
|
||||
|
||||
@@ -45,7 +45,7 @@ class DeclarationStubGenerator(
|
||||
}
|
||||
|
||||
|
||||
private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, LazyScopedTypeParametersResolver(lazyTable), true)
|
||||
private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, moduleDescriptor.builtIns, LazyScopedTypeParametersResolver(lazyTable), true)
|
||||
private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable)
|
||||
|
||||
init {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -25,11 +26,12 @@ import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
||||
class TypeTranslator(
|
||||
private val symbolTable: ReferenceSymbolTable,
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
builtIns: KotlinBuiltIns,
|
||||
private val typeParametersResolver: TypeParametersResolver = ScopedTypeParametersResolver(),
|
||||
private val enterTableScope: Boolean = false
|
||||
) {
|
||||
|
||||
private val typeApproximatorForNI = TypeApproximator()
|
||||
private val typeApproximatorForNI = TypeApproximator(builtIns)
|
||||
lateinit var constantValueGenerator: ConstantValueGenerator
|
||||
|
||||
fun enterScope(irElement: IrTypeParametersContainer) {
|
||||
@@ -124,7 +126,11 @@ class TypeTranslator(
|
||||
if (ktType.constructor.isDenotable) return ktType
|
||||
|
||||
return if (languageVersionSettings.supportsFeature(LanguageFeature.NewInference))
|
||||
typeApproximatorForNI.approximateDeclarationType(ktType, local = false, languageVersionSettings = languageVersionSettings)
|
||||
typeApproximatorForNI.approximateDeclarationType(
|
||||
ktType,
|
||||
local = false,
|
||||
languageVersionSettings = languageVersionSettings
|
||||
)
|
||||
else
|
||||
approximateCapturedTypes(ktType).upper
|
||||
}
|
||||
|
||||
+90
-63
@@ -21,17 +21,24 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.canHaveUndefinedNullability
|
||||
import org.jetbrains.kotlin.types.AbstractNullabilityChecker.hasPathByNotMarkedNullableNodes
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
|
||||
object NewCommonSuperTypeCalculator {
|
||||
|
||||
|
||||
// TODO: Bridge for old calls
|
||||
fun commonSuperType(types: List<UnwrappedType>): UnwrappedType {
|
||||
val ctx = object : ClassicTypeSystemContext {}
|
||||
return ctx.commonSuperType(types) as UnwrappedType
|
||||
}
|
||||
|
||||
fun TypeSystemCommonSuperTypesContext.commonSuperType(types: List<KotlinTypeMarker>): KotlinTypeMarker {
|
||||
val maxDepth = types.maxBy { it.typeDepth() }?.typeDepth() ?: 0
|
||||
return commonSuperType(types, -maxDepth)
|
||||
}
|
||||
|
||||
private fun commonSuperType(types: List<UnwrappedType>, depth: Int): UnwrappedType {
|
||||
private fun TypeSystemCommonSuperTypesContext.commonSuperType(types: List<KotlinTypeMarker>, depth: Int): KotlinTypeMarker {
|
||||
if (types.isEmpty()) throw IllegalStateException("Empty collection for input")
|
||||
|
||||
types.singleOrNull()?.let { return it }
|
||||
@@ -40,49 +47,57 @@ object NewCommonSuperTypeCalculator {
|
||||
|
||||
val lowers = types.map {
|
||||
when (it) {
|
||||
is SimpleType -> it
|
||||
is FlexibleType -> {
|
||||
if (it is DynamicType) return it
|
||||
is SimpleTypeMarker -> it
|
||||
is FlexibleTypeMarker -> {
|
||||
if (it.isDynamic()) return it
|
||||
// raw types are allowed here and will be transformed to FlexibleTypes
|
||||
|
||||
thereIsFlexibleTypes = true
|
||||
it.lowerBound
|
||||
it.lowerBound()
|
||||
}
|
||||
else -> error("sealed")
|
||||
}
|
||||
}
|
||||
|
||||
val lowerSuperType = commonSuperTypeForSimpleTypes(lowers, depth)
|
||||
if (!thereIsFlexibleTypes) return lowerSuperType
|
||||
|
||||
val upperSuperType = commonSuperTypeForSimpleTypes(types.map { it.upperIfFlexible() }, depth)
|
||||
return KotlinTypeFactory.flexibleType(lowerSuperType, upperSuperType)
|
||||
val upperSuperType = commonSuperTypeForSimpleTypes(types.map { it.upperBoundIfFlexible() }, depth)
|
||||
return createFlexibleType(lowerSuperType, upperSuperType)
|
||||
}
|
||||
|
||||
private fun commonSuperTypeForSimpleTypes(types: List<SimpleType>, depth: Int): SimpleType {
|
||||
private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForSimpleTypes(
|
||||
types: List<SimpleTypeMarker>,
|
||||
depth: Int
|
||||
): SimpleTypeMarker {
|
||||
// i.e. result type also should be marked nullable
|
||||
val notAllNotNull = types.any { !NullabilityChecker.isSubtypeOfAny(it) }
|
||||
val notNullTypes = if (notAllNotNull) types.map { it.makeNullableAsSpecified(false) } else types
|
||||
val notAllNotNull = types.any { !AbstractNullabilityChecker.isSubtypeOfAny(this, it) }
|
||||
val notNullTypes = if (notAllNotNull) types.map { it.withNullability(false) } else types
|
||||
|
||||
val commonSuperType = commonSuperTypeForNotNullTypes(notNullTypes, depth)
|
||||
return if (notAllNotNull)
|
||||
refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.makeNullableAsSpecified(true)
|
||||
refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.withNullability(true)
|
||||
else
|
||||
commonSuperType
|
||||
}
|
||||
|
||||
private fun refineNullabilityForUndefinedNullability(types: List<SimpleType>, commonSuperType: SimpleType): SimpleType? {
|
||||
if (!commonSuperType.unwrap().canHaveUndefinedNullability()) return null
|
||||
private fun TypeSystemCommonSuperTypesContext.refineNullabilityForUndefinedNullability(
|
||||
types: List<SimpleTypeMarker>,
|
||||
commonSuperType: SimpleTypeMarker
|
||||
): SimpleTypeMarker? {
|
||||
if (!commonSuperType.canHaveUndefinedNullability()) return null
|
||||
|
||||
val actuallyNotNull = types.all { NullabilityChecker.hasPathByNotMarkedNullableNodes(it, commonSuperType.constructor) }
|
||||
val actuallyNotNull =
|
||||
types.all { hasPathByNotMarkedNullableNodes(it, commonSuperType.typeConstructor()) }
|
||||
return if (actuallyNotNull) commonSuperType else null
|
||||
}
|
||||
|
||||
// Makes representative sample, i.e. (A, B, A) -> (A, B)
|
||||
private fun List<SimpleType>.uniquify(): List<SimpleType> {
|
||||
val uniqueTypes = arrayListOf<SimpleType>()
|
||||
for (type in this) {
|
||||
private fun TypeSystemCommonSuperTypesContext.uniquify(types: List<SimpleTypeMarker>): List<SimpleTypeMarker> {
|
||||
val uniqueTypes = arrayListOf<SimpleTypeMarker>()
|
||||
for (type in types) {
|
||||
val isNewUniqueType = uniqueTypes.all {
|
||||
!NewKotlinTypeChecker.equalTypes(it, type) || it.constructor is IntegerLiteralTypeConstructor
|
||||
!AbstractTypeChecker.equalTypes(this, it, type) || it.typeConstructor().isIntegerLiteralTypeConstructor()
|
||||
}
|
||||
if (isNewUniqueType) {
|
||||
uniqueTypes += type
|
||||
@@ -93,13 +108,13 @@ object NewCommonSuperTypeCalculator {
|
||||
|
||||
// This function leaves only supertypes, i.e. A0 is a strong supertype for A iff A != A0 && A <: A0
|
||||
// Explanation: consider types (A : A0, B : B0, A0, B0), then CST(A, B, A0, B0) == CST(CST(A, A0), CST(B, B0)) == CST(A0, B0)
|
||||
private fun List<SimpleType>.filterSupertypes(): List<SimpleType> {
|
||||
val supertypes = this.toMutableList()
|
||||
private fun TypeSystemCommonSuperTypesContext.filterSupertypes(list: List<SimpleTypeMarker>): List<SimpleTypeMarker> {
|
||||
val supertypes = list.toMutableList()
|
||||
val iterator = supertypes.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val potentialSubtype = iterator.next()
|
||||
val isSubtype = supertypes.any { supertype ->
|
||||
supertype !== potentialSubtype && NewKotlinTypeChecker.isSubtypeOf(potentialSubtype, supertype)
|
||||
supertype !== potentialSubtype && AbstractTypeChecker.isSubtypeOf(this, potentialSubtype, supertype)
|
||||
}
|
||||
|
||||
if (isSubtype) iterator.remove()
|
||||
@@ -108,28 +123,35 @@ object NewCommonSuperTypeCalculator {
|
||||
return supertypes
|
||||
}
|
||||
|
||||
private fun commonSuperTypeForNotNullTypes(types: List<SimpleType>, depth: Int): SimpleType {
|
||||
private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForNotNullTypes(
|
||||
types: List<SimpleTypeMarker>,
|
||||
depth: Int
|
||||
): SimpleTypeMarker {
|
||||
if (types.size == 1) return types.single()
|
||||
|
||||
val uniqueTypes = types.uniquify()
|
||||
val uniqueTypes = uniquify(types)
|
||||
if (uniqueTypes.size == 1) return uniqueTypes.single()
|
||||
|
||||
val explicitSupertypes = uniqueTypes.filterSupertypes()
|
||||
val explicitSupertypes = filterSupertypes(uniqueTypes)
|
||||
if (explicitSupertypes.size == 1) return explicitSupertypes.single()
|
||||
|
||||
IntegerLiteralTypeConstructor.findCommonSuperType(explicitSupertypes)?.let { return it }
|
||||
findCommonIntegerLiteralTypesSuperType(explicitSupertypes)?.let { return it }
|
||||
// IntegerLiteralTypeConstructor.findCommonSuperType(explicitSupertypes)?.let { return it }
|
||||
|
||||
return findSuperTypeConstructorsAndIntersectResult(explicitSupertypes, depth)
|
||||
}
|
||||
|
||||
private fun findSuperTypeConstructorsAndIntersectResult(types: List<SimpleType>, depth: Int): SimpleType {
|
||||
private fun TypeSystemCommonSuperTypesContext.findSuperTypeConstructorsAndIntersectResult(
|
||||
types: List<SimpleTypeMarker>,
|
||||
depth: Int
|
||||
): SimpleTypeMarker {
|
||||
return intersectTypes(allCommonSuperTypeConstructors(types).map { superTypeWithGivenConstructor(types, it, depth) })
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that if there is captured type C, then no one else is not subtype of C => lowerType cannot help here
|
||||
*/
|
||||
private fun allCommonSuperTypeConstructors(types: List<SimpleType>): List<TypeConstructor> {
|
||||
private fun TypeSystemCommonSuperTypesContext.allCommonSuperTypeConstructors(types: List<SimpleTypeMarker>): List<TypeConstructorMarker> {
|
||||
val result = collectAllSupertypes(types.first())
|
||||
for (type in types) {
|
||||
if (type === types.first()) continue
|
||||
@@ -138,22 +160,22 @@ object NewCommonSuperTypeCalculator {
|
||||
}
|
||||
return result.filterNot { target ->
|
||||
result.any { other ->
|
||||
other != target && other.supertypes.any { it.constructor == target }
|
||||
other != target && other.supertypes().any { it.typeConstructor() == target }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectAllSupertypes(type: SimpleType) = LinkedHashSet<TypeConstructor>().apply {
|
||||
type.anySuperTypeConstructor { add(it); false }
|
||||
}
|
||||
private fun TypeSystemCommonSuperTypesContext.collectAllSupertypes(type: SimpleTypeMarker) =
|
||||
LinkedHashSet<TypeConstructorMarker>().apply {
|
||||
type.anySuperTypeConstructor { add(it); false }
|
||||
}
|
||||
|
||||
private fun superTypeWithGivenConstructor(
|
||||
types: List<SimpleType>,
|
||||
constructor: TypeConstructor,
|
||||
private fun TypeSystemCommonSuperTypesContext.superTypeWithGivenConstructor(
|
||||
types: List<SimpleTypeMarker>,
|
||||
constructor: TypeConstructorMarker,
|
||||
depth: Int
|
||||
): SimpleType {
|
||||
if (constructor.parameters.isEmpty()) return KotlinTypeFactory.simpleType(
|
||||
Annotations.EMPTY,
|
||||
): SimpleTypeMarker {
|
||||
if (constructor.parametersCount() == 0) return createSimpleType(
|
||||
constructor,
|
||||
emptyList(),
|
||||
nullable = false
|
||||
@@ -168,17 +190,18 @@ object NewCommonSuperTypeCalculator {
|
||||
* but it is too complicated and we will return not so accurate type: CS(List<Int>, List<Double>, List<String>)
|
||||
*/
|
||||
val correspondingSuperTypes = types.flatMap {
|
||||
with(NewKotlinTypeChecker) {
|
||||
with(AbstractTypeChecker) {
|
||||
typeCheckerContext.findCorrespondingSupertypes(it, constructor)
|
||||
}
|
||||
}
|
||||
|
||||
val arguments = ArrayList<TypeProjection>(constructor.parameters.size)
|
||||
for ((index, parameter) in constructor.parameters.withIndex()) {
|
||||
val arguments = ArrayList<TypeArgumentMarker>(constructor.parametersCount())
|
||||
for (index in 0 until constructor.parametersCount()) {
|
||||
val parameter = constructor.getParameter(index)
|
||||
var thereIsStar = false
|
||||
val typeProjections = correspondingSuperTypes.mapNotNull {
|
||||
it.arguments.getOrNull(index)?.let {
|
||||
if (it.isStarProjection) {
|
||||
it.getArgumentOrNull(index)?.let {
|
||||
if (it.isStarProjection()) {
|
||||
thereIsStar = true
|
||||
null
|
||||
} else it
|
||||
@@ -187,38 +210,42 @@ object NewCommonSuperTypeCalculator {
|
||||
|
||||
val argument =
|
||||
if (thereIsStar || typeProjections.isEmpty()) {
|
||||
StarProjectionImpl(parameter)
|
||||
createStarProjection(parameter)
|
||||
} else {
|
||||
calculateArgument(parameter, typeProjections, depth)
|
||||
}
|
||||
|
||||
arguments.add(argument)
|
||||
}
|
||||
return KotlinTypeFactory.simpleType(Annotations.EMPTY, constructor, arguments, nullable = false)
|
||||
return createSimpleType(constructor, arguments, nullable = false)
|
||||
}
|
||||
|
||||
// no star projections in arguments
|
||||
private fun calculateArgument(parameter: TypeParameterDescriptor, arguments: List<TypeProjection>, depth: Int): TypeProjection {
|
||||
private fun TypeSystemCommonSuperTypesContext.calculateArgument(
|
||||
parameter: TypeParameterMarker,
|
||||
arguments: List<TypeArgumentMarker>,
|
||||
depth: Int
|
||||
): TypeArgumentMarker {
|
||||
if (depth > 3) {
|
||||
return StarProjectionImpl(parameter)
|
||||
return createStarProjection(parameter)
|
||||
}
|
||||
|
||||
// Inv<A>, Inv<A> = Inv<A>
|
||||
if (parameter.variance == Variance.INVARIANT && arguments.all { it.projectionKind == Variance.INVARIANT }) {
|
||||
if (parameter.getVariance() == TypeVariance.INV && arguments.all { it.getVariance() == TypeVariance.INV }) {
|
||||
val first = arguments.first()
|
||||
if (arguments.all { it.type == first.type }) return first
|
||||
if (arguments.all { it.getType() == first.getType() }) return first
|
||||
}
|
||||
|
||||
val asOut: Boolean
|
||||
if (parameter.variance != Variance.INVARIANT) {
|
||||
asOut = parameter.variance == Variance.OUT_VARIANCE
|
||||
if (parameter.getVariance() != TypeVariance.INV) {
|
||||
asOut = parameter.getVariance() == TypeVariance.OUT
|
||||
} else {
|
||||
val thereIsOut = arguments.any { it.projectionKind == Variance.OUT_VARIANCE }
|
||||
val thereIsIn = arguments.any { it.projectionKind == Variance.IN_VARIANCE }
|
||||
val thereIsOut = arguments.any { it.getVariance() == TypeVariance.OUT }
|
||||
val thereIsIn = arguments.any { it.getVariance() == TypeVariance.IN }
|
||||
if (thereIsOut) {
|
||||
if (thereIsIn) {
|
||||
// CS(Inv<out X>, Inv<in Y>) = Inv<*>
|
||||
return StarProjectionImpl(parameter)
|
||||
return createStarProjection(parameter)
|
||||
} else {
|
||||
asOut = true
|
||||
}
|
||||
@@ -230,16 +257,16 @@ object NewCommonSuperTypeCalculator {
|
||||
// CS(Out<X>, Out<Y>) = Out<CS(X, Y)>
|
||||
// CS(In<X>, In<Y>) = In<X & Y>
|
||||
if (asOut) {
|
||||
val type = commonSuperType(arguments.map { it.type.unwrap() }, depth + 1)
|
||||
return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl(
|
||||
Variance.OUT_VARIANCE,
|
||||
type
|
||||
val type = commonSuperType(arguments.map { it.getType() }, depth + 1)
|
||||
return if (parameter.getVariance() != TypeVariance.INV) return type.asTypeArgument() else createTypeArgument(
|
||||
type,
|
||||
TypeVariance.OUT
|
||||
)
|
||||
} else {
|
||||
val type = intersectTypes(arguments.map { it.type.unwrap() })
|
||||
return if (parameter.variance != Variance.INVARIANT) return type.asTypeProjection() else TypeProjectionImpl(
|
||||
Variance.IN_VARIANCE,
|
||||
type
|
||||
val type = intersectTypes(arguments.map { it.getType() })
|
||||
return if (parameter.getVariance() != TypeVariance.INV) return type.asTypeArgument() else createTypeArgument(
|
||||
type,
|
||||
TypeVariance.IN
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
|
||||
|
||||
interface BuiltInsProvider {
|
||||
val builtIns: KotlinBuiltIns
|
||||
}
|
||||
|
||||
internal val ConstraintSystemBuilder.builtIns: KotlinBuiltIns get() = ((this as NewConstraintSystemImpl).typeSystemContext as BuiltInsProvider).builtIns
|
||||
internal val NewConstraintSystem.builtIns: KotlinBuiltIns get() = ((this as NewConstraintSystemImpl).typeSystemContext as BuiltInsProvider).builtIns
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.types.StubType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContext
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class ClassicTypeSystemContextForCS(override val builtIns: KotlinBuiltIns) : TypeSystemInferenceExtensionContextDelegate,
|
||||
ClassicTypeSystemContext,
|
||||
BuiltInsProvider {
|
||||
|
||||
override fun TypeVariableMarker.defaultType(): SimpleTypeMarker {
|
||||
require(this is NewTypeVariable, this::errorMessage)
|
||||
return this.defaultType
|
||||
}
|
||||
|
||||
override fun TypeVariableMarker.freshTypeConstructor(): TypeConstructorMarker {
|
||||
require(this is NewTypeVariable, this::errorMessage)
|
||||
return this.freshTypeConstructor
|
||||
}
|
||||
|
||||
override fun createCapturedType(
|
||||
constructorProjection: TypeArgumentMarker,
|
||||
constructorSupertypes: List<KotlinTypeMarker>,
|
||||
lowerType: KotlinTypeMarker?,
|
||||
captureStatus: CaptureStatus
|
||||
): CapturedTypeMarker {
|
||||
require(lowerType is UnwrappedType?, lowerType::errorMessage)
|
||||
require(constructorProjection is TypeProjectionImpl, constructorProjection::errorMessage)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val newCapturedTypeConstructor = NewCapturedTypeConstructor(
|
||||
constructorProjection,
|
||||
constructorSupertypes as List<UnwrappedType>
|
||||
)
|
||||
return NewCapturedType(
|
||||
CaptureStatus.FOR_INCORPORATION,
|
||||
newCapturedTypeConstructor,
|
||||
lowerType = lowerType
|
||||
)
|
||||
}
|
||||
|
||||
override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker {
|
||||
return NewTypeSubstitutorByConstructorMap(map.cast())
|
||||
}
|
||||
|
||||
override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
require(type is UnwrappedType, this::errorMessage)
|
||||
require(this is NewTypeSubstitutor, this::errorMessage)
|
||||
return this.safeSubstitute(type)
|
||||
}
|
||||
|
||||
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker {
|
||||
return StubType(typeVariable.freshTypeConstructor() as TypeConstructor, typeVariable.defaultType().isMarkedNullable())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun Any?.errorMessage(): String {
|
||||
return "ClassicTypeSystemContextForCS couldn't handle: $this, ${this?.let { it::class }}"
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun NewConstraintSystemImpl(
|
||||
constraintInjector: ConstraintInjector,
|
||||
builtIns: KotlinBuiltIns
|
||||
): NewConstraintSystemImpl {
|
||||
return NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns))
|
||||
}
|
||||
+5
-2
@@ -14,10 +14,10 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empt
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.forceResolution
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||
|
||||
class KotlinCallCompleter(
|
||||
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
|
||||
@@ -196,13 +196,16 @@ class KotlinCallCompleter(
|
||||
private fun KotlinResolutionCandidate.hasProperNonTrivialLowerConstraints(typeVariable: UnwrappedType): Boolean {
|
||||
assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" }
|
||||
|
||||
val context = getSystem() as TypeSystemInferenceExtensionContext
|
||||
val constructor = typeVariable.constructor
|
||||
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false
|
||||
val constraints = variableWithConstraints.constraints
|
||||
return constraints.isNotEmpty() && constraints.all {
|
||||
!trivialConstraintTypeInferenceOracle.isTrivialConstraint(it) && it.type.constructor !is IntegerLiteralTypeConstructor &&
|
||||
!trivialConstraintTypeInferenceOracle.isTrivialConstraint(it) &&
|
||||
with(context) { !it.type.typeConstructor().isIntegerLiteralTypeConstructor() } &&
|
||||
it.kind.isLower() && csBuilder.isProperType(it.type)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.computeReturnTypeWithSmartCastInfo(
|
||||
|
||||
+17
-2
@@ -19,10 +19,13 @@ package org.jetbrains.kotlin.resolve.calls.components
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.LHSArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -141,7 +144,8 @@ private fun preprocessCallableReference(
|
||||
if (expectedType == null) return result
|
||||
|
||||
val notCallableTypeConstructor =
|
||||
csBuilder.getProperSuperTypeConstructors(expectedType).firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it) }
|
||||
csBuilder.getProperSuperTypeConstructors(expectedType)
|
||||
.firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it.requireIs()) }
|
||||
|
||||
argument.lhsResult.safeAs<LHSResult.Type>()?.let {
|
||||
val lhsType = it.unboundDetailedReceiver.stableType
|
||||
@@ -151,7 +155,13 @@ private fun preprocessCallableReference(
|
||||
}
|
||||
}
|
||||
if (notCallableTypeConstructor != null) {
|
||||
diagnosticsHolder.addDiagnostic(NotCallableExpectedType(argument, expectedType, notCallableTypeConstructor))
|
||||
diagnosticsHolder.addDiagnostic(
|
||||
NotCallableExpectedType(
|
||||
argument,
|
||||
expectedType,
|
||||
notCallableTypeConstructor.requireIs()
|
||||
)
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -163,3 +173,8 @@ private fun preprocessCollectionLiteralArgument(
|
||||
// todo add some checks about expected type
|
||||
return ResolvedCollectionLiteralAtom(collectionLiteralArgument, expectedType)
|
||||
}
|
||||
|
||||
internal inline fun <reified T : Any> Any.requireIs(): T {
|
||||
require(this is T)
|
||||
return this
|
||||
}
|
||||
+10
-10
@@ -10,22 +10,22 @@ import org.jetbrains.kotlin.resolve.calls.inference.addSubsystemFromArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.StubType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class PostponedArgumentsAnalyzer(
|
||||
private val callableReferenceResolver: CallableReferenceResolver
|
||||
) {
|
||||
interface Context {
|
||||
fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, StubType>): NewTypeSubstitutor
|
||||
fun bindingStubsForPostponedVariables(): Map<NewTypeVariable, StubType>
|
||||
interface Context : TypeSystemInferenceExtensionContext {
|
||||
fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructorMarker, StubTypeMarker>): NewTypeSubstitutor
|
||||
fun bindingStubsForPostponedVariables(): Map<TypeVariableMarker, StubTypeMarker>
|
||||
|
||||
// type can be proper if it not contains not fixed type variables
|
||||
fun canBeProper(type: UnwrappedType): Boolean
|
||||
fun canBeProper(type: KotlinTypeMarker): Boolean
|
||||
|
||||
fun hasUpperOrEqualUnitConstraint(type: UnwrappedType): Boolean
|
||||
fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean
|
||||
|
||||
// mutable operations
|
||||
fun addOtherSystem(otherSystem: ConstraintStorage)
|
||||
@@ -64,7 +64,7 @@ class PostponedArgumentsAnalyzer(
|
||||
diagnosticHolder: KotlinDiagnosticsHolder
|
||||
) {
|
||||
val stubsForPostponedVariables = c.bindingStubsForPostponedVariables()
|
||||
val currentSubstitutor = c.buildCurrentSubstitutor(stubsForPostponedVariables.mapKeys { it.key.freshTypeConstructor })
|
||||
val currentSubstitutor = c.buildCurrentSubstitutor(stubsForPostponedVariables.mapKeys { it.key.freshTypeConstructor(c) })
|
||||
|
||||
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
|
||||
|
||||
@@ -87,7 +87,7 @@ class PostponedArgumentsAnalyzer(
|
||||
receiver,
|
||||
parameters,
|
||||
expectedTypeForReturnArguments,
|
||||
stubsForPostponedVariables
|
||||
stubsForPostponedVariables.cast()
|
||||
)
|
||||
|
||||
returnArguments.forEach { c.addSubsystemFromArgument(it) }
|
||||
@@ -115,7 +115,7 @@ class PostponedArgumentsAnalyzer(
|
||||
val variable = variableWithConstraints.typeVariable
|
||||
|
||||
c.getBuilder().unmarkPostponedVariable(variable)
|
||||
c.getBuilder().addEqualityConstraint(variable.defaultType, resultType, CoroutinePosition())
|
||||
c.getBuilder().addEqualityConstraint(variable.defaultType(c), resultType, CoroutinePosition())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-13
@@ -24,27 +24,29 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
interface ConstraintSystemOperation {
|
||||
val hasContradiction: Boolean
|
||||
fun registerVariable(variable: NewTypeVariable)
|
||||
fun markPostponedVariable(variable: NewTypeVariable)
|
||||
fun unmarkPostponedVariable(variable: NewTypeVariable)
|
||||
fun registerVariable(variable: TypeVariableMarker)
|
||||
fun markPostponedVariable(variable: TypeVariableMarker)
|
||||
fun unmarkPostponedVariable(variable: TypeVariableMarker)
|
||||
|
||||
fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition)
|
||||
fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition)
|
||||
fun addSubtypeConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition)
|
||||
fun addEqualityConstraint(a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition)
|
||||
|
||||
fun isProperType(type: UnwrappedType): Boolean
|
||||
fun isTypeVariable(type: UnwrappedType): Boolean
|
||||
fun isPostponedTypeVariable(typeVariable: NewTypeVariable): Boolean
|
||||
fun isProperType(type: KotlinTypeMarker): Boolean
|
||||
fun isTypeVariable(type: KotlinTypeMarker): Boolean
|
||||
fun isPostponedTypeVariable(typeVariable: TypeVariableMarker): Boolean
|
||||
|
||||
fun getProperSuperTypeConstructors(type: UnwrappedType): List<TypeConstructor>
|
||||
fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List<TypeConstructorMarker>
|
||||
}
|
||||
|
||||
interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
||||
val builtIns: KotlinBuiltIns
|
||||
//val builtIns: KotlinBuiltIns
|
||||
// if runOperations return true, then this operation will be applied, and function return true
|
||||
fun runTransaction(runOperations: ConstraintSystemOperation.() -> Boolean): Boolean
|
||||
|
||||
@@ -54,8 +56,8 @@ interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
||||
}
|
||||
|
||||
fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(
|
||||
lowerType: UnwrappedType,
|
||||
upperType: UnwrappedType,
|
||||
lowerType: KotlinTypeMarker,
|
||||
upperType: KotlinTypeMarker,
|
||||
position: ConstraintPosition
|
||||
) =
|
||||
runTransaction {
|
||||
|
||||
+9
-5
@@ -20,11 +20,15 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.model.StubTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
fun ConstraintStorage.buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, StubType>): NewTypeSubstitutorByConstructorMap =
|
||||
NewTypeSubstitutorByConstructorMap(fixedTypeVariables.entries.associate { it.key to it.value } + additionalBindings)
|
||||
fun ConstraintStorage.buildCurrentSubstitutor(additionalBindings: Map<TypeConstructorMarker, StubTypeMarker>): NewTypeSubstitutorByConstructorMap =
|
||||
NewTypeSubstitutorByConstructorMap( (fixedTypeVariables.entries.associate { it.key to it.value } + additionalBindings).cast() ) // TODO: SUB
|
||||
|
||||
fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor {
|
||||
val currentSubstitutorMap = fixedTypeVariables.entries.associate {
|
||||
@@ -33,11 +37,11 @@ fun ConstraintStorage.buildResultingSubstitutor(): NewTypeSubstitutor {
|
||||
val uninferredSubstitutorMap = notFixedTypeVariables.entries.associate { (freshTypeConstructor, typeVariable) ->
|
||||
freshTypeConstructor to ErrorUtils.createErrorTypeWithCustomConstructor(
|
||||
"Uninferred type",
|
||||
typeVariable.typeVariable.freshTypeConstructor
|
||||
(typeVariable.typeVariable as NewTypeVariable).freshTypeConstructor// TODO: SUB
|
||||
)
|
||||
}
|
||||
|
||||
return NewTypeSubstitutorByConstructorMap(currentSubstitutorMap + uninferredSubstitutorMap)
|
||||
return NewTypeSubstitutorByConstructorMap((currentSubstitutorMap + uninferredSubstitutorMap).cast()) // TODO: SUB
|
||||
}
|
||||
|
||||
val CallableDescriptor.returnTypeOrNothing: UnwrappedType
|
||||
@@ -63,7 +67,7 @@ fun CallableDescriptor.substituteAndApproximateCapturedTypes(substitutor: NewTyp
|
||||
|
||||
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) =
|
||||
substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType ->
|
||||
TypeApproximator().approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation)
|
||||
TypeApproximator(builtIns).approximateToSuperType(substitutedType, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation)
|
||||
?: substitutedType
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
|
||||
interface NewConstraintSystem {
|
||||
val builtIns: KotlinBuiltIns
|
||||
// val builtIns: KotlinBuiltIns
|
||||
val hasContradiction: Boolean
|
||||
val diagnostics: List<KotlinCallDiagnostic>
|
||||
|
||||
|
||||
+77
-73
@@ -5,34 +5,28 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.KotlinTypeFactory.flexibleType
|
||||
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
import org.jetbrains.kotlin.types.checker.*
|
||||
import org.jetbrains.kotlin.types.model.CapturedTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
|
||||
abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext(errorTypeEqualsToAnything = true, allowedTypeVariable = false) {
|
||||
abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheckerContext(), TypeSystemInferenceExtensionContext {
|
||||
|
||||
abstract fun isMyTypeVariable(type: SimpleType): Boolean
|
||||
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
||||
get() = false
|
||||
|
||||
override val isErrorTypeEqualsToAnything: Boolean
|
||||
get() = true
|
||||
|
||||
abstract fun isMyTypeVariable(type: SimpleTypeMarker): Boolean
|
||||
|
||||
// super and sub type isSingleClassifierType
|
||||
abstract fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType)
|
||||
abstract fun addUpperConstraint(typeVariable: TypeConstructorMarker, superType: KotlinTypeMarker)
|
||||
|
||||
abstract fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType)
|
||||
abstract fun addLowerConstraint(typeVariable: TypeConstructorMarker, subType: KotlinTypeMarker)
|
||||
|
||||
override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy {
|
||||
require(subType is SimpleType)
|
||||
require(superType is NewCapturedType)
|
||||
return getLowerCapturedTypePolicy(subType, superType)
|
||||
}
|
||||
|
||||
private fun getLowerCapturedTypePolicy(subType: SimpleType, superType: NewCapturedType) = when {
|
||||
override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy = when {
|
||||
isMyTypeVariable(subType) -> LowerCapturedTypePolicy.SKIP_LOWER
|
||||
subType.contains { it.anyBound(this::isMyTypeVariable) } -> LowerCapturedTypePolicy.CHECK_ONLY_LOWER
|
||||
else -> LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER
|
||||
@@ -45,16 +39,14 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
|
||||
* override val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.TAKE_FIRST_FOR_SUBTYPING
|
||||
*/
|
||||
final override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
|
||||
require(subType is UnwrappedType)
|
||||
require(superType is UnwrappedType)
|
||||
val hasNoInfer = subType.isTypeVariableWithNoInfer() || superType.isTypeVariableWithNoInfer()
|
||||
if (hasNoInfer) return true
|
||||
|
||||
val hasExact = subType.isTypeVariableWithExact() || superType.isTypeVariableWithExact()
|
||||
|
||||
// we should strip annotation's because we have incorporation operation and they should be not affected
|
||||
val mySubType = if (hasExact) subType.replaceAnnotations(Annotations.EMPTY) else subType
|
||||
val mySuperType = if (hasExact) superType.replaceAnnotations(Annotations.EMPTY) else superType
|
||||
val mySubType = if (hasExact) subType.removeAnnotations() else subType
|
||||
val mySuperType = if (hasExact) superType.removeAnnotations() else superType
|
||||
|
||||
val result = internalAddSubtypeConstraint(mySubType, mySuperType)
|
||||
if (!hasExact) return result
|
||||
@@ -65,13 +57,13 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
|
||||
return (result ?: true) && (result2 ?: true)
|
||||
}
|
||||
|
||||
private fun UnwrappedType.isTypeVariableWithExact() =
|
||||
anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasExactAnnotation()
|
||||
private fun KotlinTypeMarker.isTypeVariableWithExact() =
|
||||
anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasExactAnnotation()
|
||||
|
||||
private fun UnwrappedType.isTypeVariableWithNoInfer() =
|
||||
anyBound(this@TypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasNoInferAnnotation()
|
||||
private fun KotlinTypeMarker.isTypeVariableWithNoInfer() =
|
||||
anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable) && hasNoInferAnnotation()
|
||||
|
||||
private fun internalAddSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType): Boolean? {
|
||||
private fun internalAddSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
|
||||
assertInputTypes(subType, superType)
|
||||
|
||||
var answer: Boolean? = null
|
||||
@@ -92,12 +84,13 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
|
||||
}
|
||||
|
||||
// extract type variable only from type like Captured(out T)
|
||||
private fun extractTypeVariableForSubtype(type: UnwrappedType): UnwrappedType? {
|
||||
if (type !is NewCapturedType) return null
|
||||
private fun extractTypeVariableForSubtype(type: KotlinTypeMarker): KotlinTypeMarker? {
|
||||
|
||||
val projection = type.constructor.projection
|
||||
return if (projection.projectionKind == Variance.OUT_VARIANCE)
|
||||
projection.type.takeIf { it is SimpleType && isMyTypeVariable(it) }?.unwrap()
|
||||
val type = type.asSimpleType()?.asCapturedType() ?: return null
|
||||
|
||||
val projection = type.typeConstructorProjection()
|
||||
return if (projection.getVariance() == TypeVariance.OUT)
|
||||
projection.getType().takeIf { it is SimpleTypeMarker && isMyTypeVariable(it) }?.asSimpleType()
|
||||
else
|
||||
null
|
||||
}
|
||||
@@ -139,35 +132,38 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
|
||||
*
|
||||
* => (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
|
||||
*/
|
||||
private fun simplifyLowerConstraint(typeVariable: UnwrappedType, subType: UnwrappedType): Boolean {
|
||||
private fun simplifyLowerConstraint(typeVariable: KotlinTypeMarker, subType: KotlinTypeMarker): Boolean {
|
||||
val lowerConstraint = when (typeVariable) {
|
||||
is SimpleType ->
|
||||
is SimpleTypeMarker ->
|
||||
// Foo <: T or
|
||||
// Foo <: T? -- Foo!! <: T
|
||||
if (typeVariable.isMarkedNullable) subType.makeDefinitelyNotNullOrNotNull() else subType
|
||||
if (typeVariable.isMarkedNullable()) subType.makeDefinitelyNotNullOrNotNull() else subType
|
||||
|
||||
is FlexibleType -> {
|
||||
is FlexibleTypeMarker -> {
|
||||
assertFlexibleTypeVariable(typeVariable)
|
||||
|
||||
when (subType) {
|
||||
is SimpleType ->
|
||||
is SimpleTypeMarker ->
|
||||
// Foo <: T! -- (Foo!! .. Foo) <: T
|
||||
flexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType)
|
||||
createFlexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType)
|
||||
|
||||
is FlexibleType ->
|
||||
is FlexibleTypeMarker ->
|
||||
// (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
|
||||
flexibleType(subType.lowerBound.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType.upperBound)
|
||||
createFlexibleType(subType.lowerBound().makeSimpleTypeDefinitelyNotNullOrNotNull(), subType.upperBound())
|
||||
|
||||
else -> error("sealed")
|
||||
}
|
||||
}
|
||||
else -> error("sealed")
|
||||
}
|
||||
|
||||
addLowerConstraint(typeVariable.constructor, lowerConstraint)
|
||||
addLowerConstraint(typeVariable.typeConstructor(), lowerConstraint)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun assertFlexibleTypeVariable(typeVariable: FlexibleType) {
|
||||
assert(typeVariable.lowerBound.constructor == typeVariable.upperBound.constructor) {
|
||||
private fun assertFlexibleTypeVariable(typeVariable: FlexibleTypeMarker) {
|
||||
assert(typeVariable.lowerBound().typeConstructor() == typeVariable.upperBound().typeConstructor()) {
|
||||
"Flexible type variable ($typeVariable) should have bounds with the same type constructor, i.e. (T..T?)"
|
||||
}
|
||||
}
|
||||
@@ -177,40 +173,46 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
|
||||
* T? <: Foo <=> T <: Foo && Nothing? <: Foo
|
||||
* T <: Foo -- leave as is
|
||||
*/
|
||||
private fun simplifyUpperConstraint(typeVariable: UnwrappedType, superType: UnwrappedType): Boolean {
|
||||
private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val typeVariable = typeVariable.lowerIfFlexible()
|
||||
val typeVariable = typeVariable.lowerBoundIfFlexible()
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val superType = if (typeVariable is DefinitelyNotNullType) superType.makeNullableAsSpecified(true) else superType
|
||||
val superType = if (typeVariable.isDefinitelyNotNullType()) superType.withNullability(true) else superType
|
||||
|
||||
addUpperConstraint(typeVariable.constructor, superType)
|
||||
addUpperConstraint(typeVariable.typeConstructor(), superType)
|
||||
|
||||
if (typeVariable.isMarkedNullable) {
|
||||
if (typeVariable.isMarkedNullable()) {
|
||||
// here is important that superType is singleClassifierType
|
||||
return superType.anyBound(this::isMyTypeVariable) ||
|
||||
isSubtypeOfByTypeChecker(typeVariable.builtIns.nullableNothingType, superType)
|
||||
isSubtypeOfByTypeChecker(nullableNothingType(), superType)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun simplifyConstraintForPossibleIntersectionSubType(subType: UnwrappedType, superType: UnwrappedType): Boolean? {
|
||||
private fun simplifyConstraintForPossibleIntersectionSubType(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val subType = subType.lowerIfFlexible()
|
||||
val subType = subType.lowerBoundIfFlexible()
|
||||
|
||||
if (!subType.isIntersectionType) return null
|
||||
if (!subType.typeConstructor().isIntersection()) return null
|
||||
|
||||
assert(!subType.isMarkedNullable) { "Intersection type should not be marked nullable!: $subType" }
|
||||
assert(!subType.isMarkedNullable()) { "Intersection type should not be marked nullable!: $subType" }
|
||||
|
||||
// TODO: may be we lose flexibility here
|
||||
val subIntersectionTypes = (subType.constructor as IntersectionTypeConstructor).supertypes.map { it.lowerIfFlexible() }
|
||||
val subIntersectionTypes = (subType.typeConstructor().supertypes()).map { it.lowerBoundIfFlexible() }
|
||||
|
||||
val typeVariables = subIntersectionTypes.filter(this::isMyTypeVariable).takeIf { it.isNotEmpty() } ?: return null
|
||||
val notTypeVariables = subIntersectionTypes.filterNot(this::isMyTypeVariable)
|
||||
|
||||
// todo: may be we can do better then that.
|
||||
if (notTypeVariables.isNotEmpty() && NewKotlinTypeChecker.isSubtypeOf(intersectTypes(notTypeVariables) as KotlinType, superType)) {
|
||||
if (notTypeVariables.isNotEmpty() &&
|
||||
AbstractTypeChecker.isSubtypeOf(
|
||||
this as TypeCheckerProviderContext,
|
||||
intersectTypes(notTypeVariables),
|
||||
superType
|
||||
)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -229,22 +231,22 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
|
||||
// here we try to add constraint {Any & T} <: S from `id(a)`
|
||||
// Previously we thought that if `Any` isn't a subtype of S => T <: S, which is wrong, now we use weaker upper constraint
|
||||
// TODO: rethink, maybe we should take nullability into account somewhere else
|
||||
if (notTypeVariables.any { NullabilityChecker.isSubtypeOfAny(it) }) {
|
||||
return typeVariables.all { simplifyUpperConstraint(it, superType.makeNullableAsSpecified(true)) }
|
||||
if (notTypeVariables.any { AbstractNullabilityChecker.isSubtypeOfAny(this as TypeCheckerProviderContext, it) }) {
|
||||
return typeVariables.all { simplifyUpperConstraint(it, superType.withNullability(true)) }
|
||||
}
|
||||
|
||||
return typeVariables.all { simplifyUpperConstraint(it, superType) }
|
||||
}
|
||||
|
||||
private fun isSubtypeOfByTypeChecker(subType: UnwrappedType, superType: UnwrappedType) =
|
||||
with(NewKotlinTypeChecker) { this@TypeCheckerContextForConstraintSystem.isSubtypeOf(subType, superType) }
|
||||
private fun isSubtypeOfByTypeChecker(subType: KotlinTypeMarker, superType: KotlinTypeMarker) =
|
||||
AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType)
|
||||
|
||||
private fun assertInputTypes(subType: UnwrappedType, superType: UnwrappedType) {
|
||||
fun correctSubType(subType: SimpleType) =
|
||||
subType.isSingleClassifierType || subType.isIntersectionType || isMyTypeVariable(subType) || subType.isError || subType.isIntegerLiteralType
|
||||
private fun assertInputTypes(subType: KotlinTypeMarker, superType: KotlinTypeMarker) {
|
||||
fun correctSubType(subType: SimpleTypeMarker) =
|
||||
subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || isMyTypeVariable(subType) || subType.isError() || subType.isIntegerLiteralType()
|
||||
|
||||
fun correctSuperType(superType: SimpleType) =
|
||||
superType.isSingleClassifierType || superType.isIntersectionType || isMyTypeVariable(superType) || superType.isError || superType.isIntegerLiteralType
|
||||
fun correctSuperType(superType: SimpleTypeMarker) =
|
||||
superType.isSingleClassifierType() || superType.typeConstructor().isIntersection() || isMyTypeVariable(superType) || superType.isError() || superType.isIntegerLiteralType()
|
||||
|
||||
assert(subType.bothBounds(::correctSubType)) {
|
||||
"Not singleClassifierType and not intersection subType: $subType"
|
||||
@@ -254,13 +256,15 @@ abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun UnwrappedType.bothBounds(f: (SimpleType) -> Boolean) = when (this) {
|
||||
is SimpleType -> f(this)
|
||||
is FlexibleType -> f(lowerBound) && f(upperBound)
|
||||
private inline fun KotlinTypeMarker.bothBounds(f: (SimpleTypeMarker) -> Boolean) = when (this) {
|
||||
is SimpleTypeMarker -> f(this)
|
||||
is FlexibleTypeMarker -> f(lowerBound()) && f(upperBound())
|
||||
else -> error("sealed")
|
||||
}
|
||||
|
||||
private inline fun UnwrappedType.anyBound(f: (SimpleType) -> Boolean) = when (this) {
|
||||
is SimpleType -> f(this)
|
||||
is FlexibleType -> f(lowerBound) || f(upperBound)
|
||||
private inline fun KotlinTypeMarker.anyBound(f: (SimpleTypeMarker) -> Boolean) = when (this) {
|
||||
is SimpleTypeMarker -> f(this)
|
||||
is FlexibleTypeMarker -> f(lowerBound()) || f(upperBound())
|
||||
else -> error("sealed")
|
||||
}
|
||||
}
|
||||
+81
-54
@@ -7,13 +7,9 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
|
||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
@@ -24,130 +20,161 @@ class ConstraintIncorporator(
|
||||
val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
|
||||
) {
|
||||
|
||||
interface Context {
|
||||
interface Context : TypeSystemInferenceExtensionContext {
|
||||
val allTypeVariablesWithConstraints: Collection<VariableWithConstraints>
|
||||
|
||||
// if such type variable is fixed then it is error
|
||||
fun getTypeVariable(typeConstructor: TypeConstructor): NewTypeVariable?
|
||||
fun getTypeVariable(typeConstructor: TypeConstructorMarker): TypeVariableMarker?
|
||||
|
||||
fun getConstraintsForVariable(typeVariable: NewTypeVariable): Collection<Constraint>
|
||||
fun getConstraintsForVariable(typeVariable: TypeVariableMarker): Collection<Constraint>
|
||||
|
||||
fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType)
|
||||
fun addNewIncorporatedConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker)
|
||||
}
|
||||
|
||||
// \alpha is typeVariable, \beta -- other type variable registered in ConstraintStorage
|
||||
fun incorporate(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) {
|
||||
fun incorporate(c: Context, typeVariable: TypeVariableMarker, constraint: Constraint) {
|
||||
// we shouldn't incorporate recursive constraint -- It is too dangerous
|
||||
if (constraint.type.contains { it.constructor == typeVariable.freshTypeConstructor }) return
|
||||
with(c) {
|
||||
if (constraint.type.contains { it.typeConstructor() == typeVariable.freshTypeConstructor() }) return
|
||||
}
|
||||
|
||||
directWithVariable(c, typeVariable, constraint)
|
||||
otherInsideMyConstraint(c, typeVariable, constraint)
|
||||
insideOtherConstraint(c, typeVariable, constraint)
|
||||
c.directWithVariable(typeVariable, constraint)
|
||||
c.otherInsideMyConstraint(typeVariable, constraint)
|
||||
c.insideOtherConstraint(typeVariable, constraint)
|
||||
}
|
||||
|
||||
// A <:(=) \alpha <:(=) B => A <: B
|
||||
private fun directWithVariable(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) {
|
||||
private fun Context.directWithVariable(
|
||||
typeVariable: TypeVariableMarker,
|
||||
constraint: Constraint
|
||||
) {
|
||||
// \alpha <: constraint.type
|
||||
if (constraint.kind != ConstraintKind.LOWER) {
|
||||
c.getConstraintsForVariable(typeVariable).forEach {
|
||||
getConstraintsForVariable(typeVariable).forEach {
|
||||
if (it.kind != ConstraintKind.UPPER) {
|
||||
c.addNewIncorporatedConstraint(it.type, constraint.type)
|
||||
addNewIncorporatedConstraint(it.type, constraint.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// constraint.type <: \alpha
|
||||
if (constraint.kind != ConstraintKind.UPPER) {
|
||||
c.getConstraintsForVariable(typeVariable).forEach {
|
||||
getConstraintsForVariable(typeVariable).forEach {
|
||||
if (it.kind != ConstraintKind.LOWER) {
|
||||
c.addNewIncorporatedConstraint(constraint.type, it.type)
|
||||
addNewIncorporatedConstraint(constraint.type, it.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// \alpha <: Inv<\beta>, \beta <: Number => \alpha <: Inv<out Number>
|
||||
private fun otherInsideMyConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) {
|
||||
val otherInMyConstraint = SmartSet.create<NewTypeVariable>()
|
||||
private fun Context.otherInsideMyConstraint(
|
||||
typeVariable: TypeVariableMarker,
|
||||
constraint: Constraint
|
||||
) {
|
||||
val otherInMyConstraint = SmartSet.create<TypeVariableMarker>()
|
||||
constraint.type.contains {
|
||||
otherInMyConstraint.addIfNotNull(c.getTypeVariable(it.constructor))
|
||||
otherInMyConstraint.addIfNotNull(this.getTypeVariable(it.typeConstructor()))
|
||||
false
|
||||
}
|
||||
|
||||
for (otherTypeVariable in otherInMyConstraint) {
|
||||
// to avoid ConcurrentModificationException
|
||||
val otherConstraints = ArrayList(c.getConstraintsForVariable(otherTypeVariable))
|
||||
val otherConstraints = ArrayList(this.getConstraintsForVariable(otherTypeVariable))
|
||||
for (otherConstraint in otherConstraints) {
|
||||
generateNewConstraint(c, typeVariable, constraint, otherTypeVariable, otherConstraint)
|
||||
generateNewConstraint(typeVariable, constraint, otherTypeVariable, otherConstraint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// \alpha <: Number, \beta <: Inv<\alpha> => \beta <: Inv<out Number>
|
||||
private fun insideOtherConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) {
|
||||
for (typeVariableWithConstraint in c.allTypeVariablesWithConstraints) {
|
||||
private fun Context.insideOtherConstraint(
|
||||
typeVariable: TypeVariableMarker,
|
||||
constraint: Constraint
|
||||
) {
|
||||
for (typeVariableWithConstraint in this@insideOtherConstraint.allTypeVariablesWithConstraints) {
|
||||
val constraintsWhichConstraintMyVariable = typeVariableWithConstraint.constraints.filter {
|
||||
it.type.contains { it.constructor == typeVariable.freshTypeConstructor }
|
||||
it.type.contains { it.typeConstructor() == typeVariable.freshTypeConstructor() }
|
||||
}
|
||||
constraintsWhichConstraintMyVariable.forEach {
|
||||
generateNewConstraint(c, typeVariableWithConstraint.typeVariable, it, typeVariable, constraint)
|
||||
generateNewConstraint(typeVariableWithConstraint.typeVariable, it, typeVariable, constraint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateNewConstraint(
|
||||
c: Context,
|
||||
targetVariable: NewTypeVariable,
|
||||
private fun Context.generateNewConstraint(
|
||||
targetVariable: TypeVariableMarker,
|
||||
baseConstraint: Constraint,
|
||||
otherVariable: NewTypeVariable,
|
||||
otherVariable: TypeVariableMarker,
|
||||
otherConstraint: Constraint
|
||||
) {
|
||||
|
||||
val baseConstraintType = baseConstraint.type
|
||||
|
||||
val typeForApproximation = when (otherConstraint.kind) {
|
||||
ConstraintKind.EQUALITY -> {
|
||||
baseConstraintType.substituteTypeVariable(otherVariable, otherConstraint.type)
|
||||
baseConstraintType.substitute(this, otherVariable, otherConstraint.type)
|
||||
}
|
||||
ConstraintKind.UPPER -> {
|
||||
val newCapturedTypeConstructor = NewCapturedTypeConstructor(
|
||||
TypeProjectionImpl(Variance.OUT_VARIANCE, otherConstraint.type),
|
||||
listOf(otherConstraint.type)
|
||||
val temporaryCapturedType = createCapturedType(
|
||||
createTypeArgument(otherConstraint.type, TypeVariance.OUT),
|
||||
listOf(otherConstraint.type),
|
||||
null,
|
||||
CaptureStatus.FOR_INCORPORATION
|
||||
)
|
||||
val temporaryCapturedType = NewCapturedType(
|
||||
CaptureStatus.FOR_INCORPORATION,
|
||||
newCapturedTypeConstructor,
|
||||
lowerType = null
|
||||
)
|
||||
baseConstraintType.substituteTypeVariable(otherVariable, temporaryCapturedType)
|
||||
// val newCapturedTypeConstructor = NewCapturedTypeConstructor(
|
||||
// TypeProjectionImpl(Variance.OUT_VARIANCE, otherConstraint.type),
|
||||
// listOf(otherConstraint.type)
|
||||
// )
|
||||
// val temporaryCapturedType = NewCapturedType(
|
||||
// CaptureStatus.FOR_INCORPORATION,
|
||||
// newCapturedTypeConstructor,
|
||||
// lowerType = null
|
||||
// )
|
||||
baseConstraintType.substitute(this, otherVariable, temporaryCapturedType)
|
||||
}
|
||||
ConstraintKind.LOWER -> {
|
||||
val newCapturedTypeConstructor = NewCapturedTypeConstructor(
|
||||
TypeProjectionImpl(Variance.IN_VARIANCE, otherConstraint.type),
|
||||
emptyList()
|
||||
val temporaryCapturedType = createCapturedType(
|
||||
createTypeArgument(otherConstraint.type, TypeVariance.IN),
|
||||
emptyList(),
|
||||
otherConstraint.type,
|
||||
CaptureStatus.FOR_INCORPORATION
|
||||
)
|
||||
val temporaryCapturedType = NewCapturedType(
|
||||
CaptureStatus.FOR_INCORPORATION,
|
||||
newCapturedTypeConstructor,
|
||||
lowerType = otherConstraint.type
|
||||
)
|
||||
baseConstraintType.substituteTypeVariable(otherVariable, temporaryCapturedType)
|
||||
|
||||
// val newCapturedTypeConstructor = NewCapturedTypeConstructor(
|
||||
// TypeProjectionImpl(Variance.IN_VARIANCE, otherConstraint.type),
|
||||
// emptyList()
|
||||
// )
|
||||
// val temporaryCapturedType = NewCapturedType(
|
||||
// CaptureStatus.FOR_INCORPORATION,
|
||||
// newCapturedTypeConstructor,
|
||||
// lowerType = otherConstraint.type
|
||||
// )
|
||||
baseConstraintType.substitute(this, otherVariable, temporaryCapturedType)
|
||||
}
|
||||
}
|
||||
|
||||
if (baseConstraint.kind != ConstraintKind.UPPER) {
|
||||
val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = false)
|
||||
if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) {
|
||||
c.addNewIncorporatedConstraint(generatedConstraintType, targetVariable.defaultType)
|
||||
addNewIncorporatedConstraint(generatedConstraintType, targetVariable.defaultType())
|
||||
}
|
||||
}
|
||||
if (baseConstraint.kind != ConstraintKind.LOWER) {
|
||||
val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = true)
|
||||
if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) {
|
||||
c.addNewIncorporatedConstraint(targetVariable.defaultType, generatedConstraintType)
|
||||
addNewIncorporatedConstraint(targetVariable.defaultType(), generatedConstraintType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun approximateCapturedTypes(type: UnwrappedType, toSuper: Boolean): UnwrappedType =
|
||||
private fun KotlinTypeMarker.substitute(c: Context, typeVariable: TypeVariableMarker, value: KotlinTypeMarker): KotlinTypeMarker {
|
||||
val substitutor = c.typeSubstitutorByTypeConstructor(mapOf(typeVariable.freshTypeConstructor(c) to value))
|
||||
return substitutor.safeSubstitute(c, this)
|
||||
}
|
||||
|
||||
|
||||
private fun approximateCapturedTypes(type: KotlinTypeMarker, toSuper: Boolean): KotlinTypeMarker =
|
||||
if (toSuper) typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type
|
||||
else typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.IncorporationConfiguration) ?: type
|
||||
}
|
||||
|
||||
+54
-46
@@ -16,35 +16,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.LOWER
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.UPPER
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import java.util.*
|
||||
|
||||
class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val typeApproximator: TypeApproximator) {
|
||||
private val ALLOWED_DEPTH_DELTA_FOR_INCORPORATION = 1
|
||||
|
||||
interface Context {
|
||||
val allTypeVariables: Map<TypeConstructor, NewTypeVariable>
|
||||
interface Context : TypeSystemInferenceExtensionContext {
|
||||
val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
|
||||
|
||||
var maxTypeDepthFromInitialConstraints: Int
|
||||
val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints>
|
||||
val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType>
|
||||
val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints>
|
||||
val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker>
|
||||
|
||||
fun addInitialConstraint(initialConstraint: InitialConstraint)
|
||||
fun addError(error: KotlinCallDiagnostic)
|
||||
}
|
||||
|
||||
fun addInitialSubtypeConstraint(c: Context, lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) {
|
||||
fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) {
|
||||
val initialConstraint = InitialConstraint(lowerType, upperType, UPPER, position)
|
||||
val incorporationPosition = IncorporationConstraintPosition(position, initialConstraint)
|
||||
c.addInitialConstraint(initialConstraint)
|
||||
@@ -53,7 +49,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
addSubTypeConstraintAndIncorporateIt(c, lowerType, upperType, incorporationPosition)
|
||||
}
|
||||
|
||||
fun addInitialEqualityConstraint(c: Context, a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) {
|
||||
fun addInitialEqualityConstraint(c: Context, a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) {
|
||||
val initialConstraint = InitialConstraint(a, b, ConstraintKind.EQUALITY, position)
|
||||
val incorporationPosition = IncorporationConstraintPosition(position, initialConstraint)
|
||||
c.addInitialConstraint(initialConstraint)
|
||||
@@ -66,11 +62,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
|
||||
private fun addSubTypeConstraintAndIncorporateIt(
|
||||
c: Context,
|
||||
lowerType: UnwrappedType,
|
||||
upperType: UnwrappedType,
|
||||
lowerType: KotlinTypeMarker,
|
||||
upperType: KotlinTypeMarker,
|
||||
incorporatePosition: IncorporationConstraintPosition
|
||||
) {
|
||||
val possibleNewConstraints = Stack<Pair<NewTypeVariable, Constraint>>()
|
||||
val possibleNewConstraints = Stack<Pair<TypeVariableMarker, Constraint>>()
|
||||
val typeCheckerContext = TypeCheckerContext(c, incorporatePosition, lowerType, upperType, possibleNewConstraints)
|
||||
typeCheckerContext.runIsSubtypeOf(lowerType, upperType)
|
||||
|
||||
@@ -79,7 +75,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
if (c.shouldWeSkipConstraint(typeVariable, constraint)) continue
|
||||
|
||||
val constraints =
|
||||
c.notFixedTypeVariables[typeVariable.freshTypeConstructor] ?: typeCheckerContext.fixedTypeVariable(typeVariable)
|
||||
c.notFixedTypeVariables[typeVariable.freshTypeConstructor(c)] ?: typeCheckerContext.fixedTypeVariable(typeVariable)
|
||||
|
||||
// it is important, that we add constraint here(not inside TypeCheckerContext), because inside incorporation we read constraints
|
||||
constraints.addConstraint(constraint)?.let {
|
||||
@@ -88,59 +84,71 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAllowedTypeDepth(c: Context, initialType: UnwrappedType) {
|
||||
private fun updateAllowedTypeDepth(c: Context, initialType: KotlinTypeMarker) = with(c) {
|
||||
c.maxTypeDepthFromInitialConstraints = Math.max(c.maxTypeDepthFromInitialConstraints, initialType.typeDepth())
|
||||
}
|
||||
|
||||
private fun Context.shouldWeSkipConstraint(typeVariable: NewTypeVariable, constraint: Constraint): Boolean {
|
||||
private fun Context.shouldWeSkipConstraint(typeVariable: TypeVariableMarker, constraint: Constraint): Boolean {
|
||||
assert(constraint.kind != ConstraintKind.EQUALITY)
|
||||
|
||||
val constraintType = constraint.type
|
||||
if (!isAllowedType(constraintType)) return true
|
||||
|
||||
if (constraintType.constructor == typeVariable.freshTypeConstructor) {
|
||||
if (constraintType.lowerIfFlexible().isMarkedNullable && constraint.kind == LOWER) return false // T? <: T
|
||||
if (constraintType.typeConstructor() == typeVariable.freshTypeConstructor()) {
|
||||
if (constraintType.lowerBoundIfFlexible().isMarkedNullable() && constraint.kind == LOWER) return false // T? <: T
|
||||
|
||||
return true // T <: T(?!)
|
||||
}
|
||||
|
||||
if (constraintType is SimpleType) {
|
||||
if (constraintType.isSimpleType()) {
|
||||
if (constraint.kind == UPPER && constraintType.isNullableAny()) return true // T <: Any?
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun Context.isAllowedType(type: UnwrappedType) =
|
||||
private fun Context.isAllowedType(type: KotlinTypeMarker) =
|
||||
type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION
|
||||
|
||||
private inner class TypeCheckerContext(
|
||||
val c: Context,
|
||||
val position: IncorporationConstraintPosition,
|
||||
val baseLowerType: UnwrappedType,
|
||||
val baseUpperType: UnwrappedType,
|
||||
val possibleNewConstraints: MutableList<Pair<NewTypeVariable, Constraint>>
|
||||
) : TypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context {
|
||||
val baseLowerType: KotlinTypeMarker,
|
||||
val baseUpperType: KotlinTypeMarker,
|
||||
val possibleNewConstraints: MutableList<Pair<TypeVariableMarker, Constraint>>
|
||||
) : AbstractTypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c {
|
||||
|
||||
fun runIsSubtypeOf(lowerType: UnwrappedType, upperType: UnwrappedType) {
|
||||
with(NewKotlinTypeChecker) {
|
||||
if (!this@TypeCheckerContext.isSubtypeOf(lowerType, upperType)) {
|
||||
// todo improve error reporting -- add information about base types
|
||||
c.addError(NewConstraintError(lowerType, upperType, position))
|
||||
}
|
||||
val baseContext: AbstractTypeCheckerContext = newBaseTypeCheckerContext(isErrorTypeEqualsToAnything)
|
||||
|
||||
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
|
||||
return baseContext.substitutionSupertypePolicy(type)
|
||||
}
|
||||
|
||||
override fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean {
|
||||
return baseContext.areEqualTypeConstructors(a, b)
|
||||
}
|
||||
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return baseContext.prepareType(type)
|
||||
}
|
||||
|
||||
fun runIsSubtypeOf(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) {
|
||||
if (!AbstractTypeChecker.isSubtypeOf(this@TypeCheckerContext as AbstractTypeCheckerContext, lowerType, upperType)) {
|
||||
// todo improve error reporting -- add information about base types
|
||||
c.addError(NewConstraintError(lowerType, upperType, position))
|
||||
}
|
||||
}
|
||||
|
||||
// from TypeCheckerContextForConstraintSystem
|
||||
override fun isMyTypeVariable(type: SimpleType): Boolean = c.allTypeVariables.containsKey(type.constructor)
|
||||
// from AbstractTypeCheckerContextForConstraintSystem
|
||||
override fun isMyTypeVariable(type: SimpleTypeMarker): Boolean = c.allTypeVariables.containsKey(type.typeConstructor())
|
||||
|
||||
override fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType) =
|
||||
override fun addUpperConstraint(typeVariable: TypeConstructorMarker, superType: KotlinTypeMarker) =
|
||||
addConstraint(typeVariable, superType, UPPER)
|
||||
|
||||
override fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType) =
|
||||
override fun addLowerConstraint(typeVariable: TypeConstructorMarker, subType: KotlinTypeMarker) =
|
||||
addConstraint(typeVariable, subType, LOWER)
|
||||
|
||||
private fun isCapturedTypeFromSubtyping(type: UnwrappedType) =
|
||||
private fun isCapturedTypeFromSubtyping(type: KotlinTypeMarker) =
|
||||
when ((type as? NewCapturedType)?.captureStatus) {
|
||||
null, CaptureStatus.FROM_EXPRESSION -> false
|
||||
CaptureStatus.FOR_SUBTYPING -> true
|
||||
@@ -148,12 +156,12 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
error("Captured type for incorporation shouldn't escape from incorporation: $type\n" + renderBaseConstraint())
|
||||
}
|
||||
|
||||
private fun addConstraint(typeVariableConstructor: TypeConstructor, type: UnwrappedType, kind: ConstraintKind) {
|
||||
private fun addConstraint(typeVariableConstructor: TypeConstructorMarker, type: KotlinTypeMarker, kind: ConstraintKind) {
|
||||
val typeVariable = c.allTypeVariables[typeVariableConstructor]
|
||||
?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}")
|
||||
|
||||
var targetType = type
|
||||
if (targetType.isError) {
|
||||
if (targetType.isError()) {
|
||||
c.addError(ConstrainingTypeIsError(typeVariable, targetType, position))
|
||||
return
|
||||
}
|
||||
@@ -163,7 +171,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
if (kind == UPPER) {
|
||||
val subType =
|
||||
typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
|
||||
if (subType != null && !KotlinBuiltIns.isNothingOrNullableNothing(subType)) {
|
||||
if (subType != null && !subType.typeConstructor().isNothingConstructor()) {
|
||||
targetType = subType
|
||||
}
|
||||
}
|
||||
@@ -171,7 +179,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
if (kind == LOWER) {
|
||||
val superType =
|
||||
typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
|
||||
if (superType != null && !KotlinBuiltIns.isAnyOrNullableAny(superType)) { // todo rethink error reporting for Any cases
|
||||
if (superType != null && !superType.typeConstructor().isAnyConstructor()) { // todo rethink error reporting for Any cases
|
||||
targetType = superType
|
||||
}
|
||||
}
|
||||
@@ -186,7 +194,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
}
|
||||
|
||||
// from ConstraintIncorporator.Context
|
||||
override fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType) {
|
||||
override fun addNewIncorporatedConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) {
|
||||
if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) {
|
||||
runIsSubtypeOf(lowerType, upperType)
|
||||
}
|
||||
@@ -195,7 +203,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
override val allTypeVariablesWithConstraints: Collection<VariableWithConstraints>
|
||||
get() = c.notFixedTypeVariables.values
|
||||
|
||||
override fun getTypeVariable(typeConstructor: TypeConstructor): NewTypeVariable? {
|
||||
override fun getTypeVariable(typeConstructor: TypeConstructorMarker): TypeVariableMarker? {
|
||||
val typeVariable = c.allTypeVariables[typeConstructor]
|
||||
if (typeVariable != null && !c.notFixedTypeVariables.containsKey(typeConstructor)) {
|
||||
fixedTypeVariable(typeVariable)
|
||||
@@ -203,11 +211,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
return typeVariable
|
||||
}
|
||||
|
||||
override fun getConstraintsForVariable(typeVariable: NewTypeVariable) =
|
||||
c.notFixedTypeVariables[typeVariable.freshTypeConstructor]?.constraints
|
||||
override fun getConstraintsForVariable(typeVariable: TypeVariableMarker) =
|
||||
c.notFixedTypeVariables[typeVariable.freshTypeConstructor()]?.constraints
|
||||
?: fixedTypeVariable(typeVariable)
|
||||
|
||||
fun fixedTypeVariable(variable: NewTypeVariable): Nothing {
|
||||
fun fixedTypeVariable(variable: TypeVariableMarker): Nothing {
|
||||
error(
|
||||
"Type variable $variable should not be fixed!\n" +
|
||||
renderBaseConstraint()
|
||||
|
||||
+10
-6
@@ -11,7 +11,11 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraint
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
@@ -25,19 +29,19 @@ class KotlinConstraintSystemCompleter(
|
||||
}
|
||||
|
||||
interface Context : VariableFixationFinder.Context, ResultTypeResolver.Context {
|
||||
override val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>
|
||||
override val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
|
||||
|
||||
override val postponedTypeVariables: List<NewTypeVariable>
|
||||
override val postponedTypeVariables: List<TypeVariableMarker>
|
||||
|
||||
// type can be proper if it not contains not fixed type variables
|
||||
fun canBeProper(type: UnwrappedType): Boolean
|
||||
fun canBeProper(type: KotlinTypeMarker): Boolean
|
||||
|
||||
fun containsOnlyFixedOrPostponedVariables(type: UnwrappedType): Boolean
|
||||
fun containsOnlyFixedOrPostponedVariables(type: KotlinTypeMarker): Boolean
|
||||
|
||||
// mutable operations
|
||||
fun addError(error: KotlinCallDiagnostic)
|
||||
|
||||
fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType)
|
||||
fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker)
|
||||
}
|
||||
|
||||
fun runCompletion(
|
||||
@@ -157,7 +161,7 @@ class KotlinConstraintSystemCompleter(
|
||||
c: Context,
|
||||
collectVariablesFromContext: Boolean,
|
||||
topLevelAtoms: List<ResolvedAtom>
|
||||
): List<TypeConstructor> {
|
||||
): List<TypeConstructorMarker> {
|
||||
if (collectVariablesFromContext) return c.notFixedTypeVariables.keys.toList()
|
||||
|
||||
fun ResolvedAtom.process(to: LinkedHashSet<TypeConstructor>) {
|
||||
|
||||
+2
-1
@@ -12,8 +12,9 @@ import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
|
||||
import org.jetbrains.kotlin.types.checker.intersectTypes
|
||||
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||
|
||||
interface NewTypeSubstitutor {
|
||||
interface NewTypeSubstitutor: TypeSubstitutorMarker {
|
||||
fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType?
|
||||
|
||||
fun safeSubstitute(type: UnwrappedType): UnwrappedType = substitute(type, runCapturedChecks = true, keepAnnotation = false) ?: type
|
||||
|
||||
+27
-29
@@ -24,33 +24,31 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.checkConstraint
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.intersectTypes
|
||||
import org.jetbrains.kotlin.types.checker.isIntegerLiteralType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||
|
||||
class ResultTypeResolver(
|
||||
val typeApproximator: TypeApproximator,
|
||||
val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
|
||||
) {
|
||||
interface Context {
|
||||
fun isProperType(type: UnwrappedType): Boolean
|
||||
interface Context : TypeSystemInferenceExtensionContext {
|
||||
fun isProperType(type: KotlinTypeMarker): Boolean
|
||||
}
|
||||
|
||||
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): UnwrappedType {
|
||||
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker {
|
||||
findResultTypeOrNull(c, variableWithConstraints, direction)?.let { return it }
|
||||
|
||||
// no proper constraints
|
||||
return variableWithConstraints.typeVariable.freshTypeConstructor.builtIns.run {
|
||||
if (direction == ResolveDirection.TO_SUBTYPE) nothingType else nullableAnyType
|
||||
return run {
|
||||
if (direction == ResolveDirection.TO_SUBTYPE) c.nothingType() else c.nullableAnyType()
|
||||
}
|
||||
}
|
||||
|
||||
fun findResultTypeOrNull(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): UnwrappedType? {
|
||||
fun findResultTypeOrNull(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker? {
|
||||
findResultIfThereIsEqualsConstraint(c, variableWithConstraints)?.let { return it }
|
||||
|
||||
val subType = findSubType(c, variableWithConstraints)
|
||||
val superType = findSuperType(c, variableWithConstraints)
|
||||
val subType = c.findSubType(variableWithConstraints)
|
||||
val superType = c.findSuperType(variableWithConstraints)
|
||||
val result = if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) {
|
||||
c.resultType(subType, superType, variableWithConstraints)
|
||||
} else {
|
||||
@@ -61,10 +59,10 @@ class ResultTypeResolver(
|
||||
}
|
||||
|
||||
private fun Context.resultType(
|
||||
firstCandidate: UnwrappedType?,
|
||||
secondCandidate: UnwrappedType?,
|
||||
firstCandidate: KotlinTypeMarker?,
|
||||
secondCandidate: KotlinTypeMarker?,
|
||||
variableWithConstraints: VariableWithConstraints
|
||||
): UnwrappedType? {
|
||||
): KotlinTypeMarker? {
|
||||
if (firstCandidate == null || secondCandidate == null) return firstCandidate ?: secondCandidate
|
||||
|
||||
if (isSuitableType(firstCandidate, variableWithConstraints)) return firstCandidate
|
||||
@@ -76,7 +74,7 @@ class ResultTypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Context.isSuitableType(resultType: UnwrappedType, variableWithConstraints: VariableWithConstraints): Boolean {
|
||||
private fun Context.isSuitableType(resultType: KotlinTypeMarker, variableWithConstraints: VariableWithConstraints): Boolean {
|
||||
for (constraint in variableWithConstraints.constraints) {
|
||||
if (!isProperType(constraint.type)) continue
|
||||
if (!checkConstraint(constraint.type, constraint.kind, resultType)) return false
|
||||
@@ -87,11 +85,11 @@ class ResultTypeResolver(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun findSubType(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? {
|
||||
val lowerConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.LOWER && c.isProperType(it.type) }
|
||||
private fun Context.findSubType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
|
||||
val lowerConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.LOWER && isProperType(it.type) }
|
||||
if (lowerConstraints.isNotEmpty()) {
|
||||
val types = sinkIntegerLiteralTypes(lowerConstraints.map { it.type })
|
||||
val commonSuperType = NewCommonSuperTypeCalculator.commonSuperType(types)
|
||||
val commonSuperType = with(NewCommonSuperTypeCalculator) { commonSuperType(types) }
|
||||
/**
|
||||
*
|
||||
* fun <T> Array<out T>.intersect(other: Iterable<T>) {
|
||||
@@ -119,16 +117,16 @@ class ResultTypeResolver(
|
||||
return null
|
||||
}
|
||||
|
||||
private fun sinkIntegerLiteralTypes(types: List<UnwrappedType>): List<UnwrappedType> {
|
||||
private fun Context.sinkIntegerLiteralTypes(types: List<KotlinTypeMarker>): List<KotlinTypeMarker> {
|
||||
return types.sortedBy { type ->
|
||||
|
||||
val containsILT = type.contains { it.unwrap().safeAs<SimpleType>()?.isIntegerLiteralType ?: false }
|
||||
val containsILT = type.contains { it.asSimpleType()?.isIntegerLiteralType() ?: false }
|
||||
if (containsILT) 1 else 0
|
||||
}
|
||||
}
|
||||
|
||||
private fun findSuperType(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? {
|
||||
val upperConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && c.isProperType(it.type) }
|
||||
private fun Context.findSuperType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
|
||||
val upperConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && this@findSuperType.isProperType(it.type) }
|
||||
if (upperConstraints.isNotEmpty()) {
|
||||
val upperType = intersectTypes(upperConstraints.map { it.type })
|
||||
|
||||
@@ -137,22 +135,22 @@ class ResultTypeResolver(
|
||||
return null
|
||||
}
|
||||
|
||||
fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? {
|
||||
fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? = with(c) {
|
||||
val properEqualityConstraints = variableWithConstraints.constraints.filter {
|
||||
it.kind == ConstraintKind.EQUALITY && c.isProperType(it.type)
|
||||
}
|
||||
|
||||
return representativeFromEqualityConstraints(properEqualityConstraints)
|
||||
return c.representativeFromEqualityConstraints(properEqualityConstraints)
|
||||
}
|
||||
|
||||
// Discriminate integer literal types as they are less specific than separate integer types (Int, Short...)
|
||||
private fun representativeFromEqualityConstraints(constraints: List<Constraint>): UnwrappedType? {
|
||||
private fun Context.representativeFromEqualityConstraints(constraints: List<Constraint>): KotlinTypeMarker? {
|
||||
if (constraints.isEmpty()) return null
|
||||
|
||||
val constraintTypes = constraints.map { it.type }
|
||||
val nonLiteralTypes = constraintTypes.filter { it.constructor !is IntegerLiteralTypeConstructor }
|
||||
return nonLiteralTypes.singleBestRepresentative()?.unwrap()
|
||||
?: constraintTypes.singleBestRepresentative()?.unwrap()
|
||||
val nonLiteralTypes = constraintTypes.filter { it.typeConstructor() !is IntegerLiteralTypeConstructor }
|
||||
return nonLiteralTypes.singleBestRepresentative()
|
||||
?: constraintTypes.singleBestRepresentative()
|
||||
?: constraintTypes.first() // seems like constraint system has contradiction
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||
@@ -31,7 +32,8 @@ import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
|
||||
|
||||
class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns) : SimpleConstraintSystem {
|
||||
val csBuilder: ConstraintSystemBuilder = NewConstraintSystemImpl(constraintInjector, builtIns).getBuilder()
|
||||
val csBuilder: ConstraintSystemBuilder =
|
||||
NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns)).getBuilder()
|
||||
|
||||
override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>): TypeSubstitutor {
|
||||
val substitutionMap = typeParameters.associate {
|
||||
|
||||
+23
-17
@@ -7,26 +7,29 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullableNothing
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate
|
||||
|
||||
class TrivialConstraintTypeInferenceOracle {
|
||||
class TrivialConstraintTypeInferenceOracle(context: TypeSystemInferenceExtensionContextDelegate) :
|
||||
TypeSystemInferenceExtensionContext by context {
|
||||
// The idea is to add knowledge that constraint `Nothing(?) <: T` is quite useless and
|
||||
// it's totally fine to go and resolve postponed argument without fixation T to Nothing(?).
|
||||
// In other words, constraint `Nothing(?) <: T` is *not* proper
|
||||
fun isTrivialConstraint(constraint: Constraint): Boolean {
|
||||
fun isTrivialConstraint(
|
||||
constraint: Constraint
|
||||
): Boolean {
|
||||
// TODO: probably we also can take into account `T <: Any(?)` constraints
|
||||
return constraint.kind == ConstraintKind.LOWER && constraint.type.isNothingOrNullableNothing()
|
||||
return constraint.kind == ConstraintKind.LOWER && constraint.type.typeConstructor().isNothingConstructor()
|
||||
}
|
||||
|
||||
// This function controls the choice between sub and super result type
|
||||
// Even that Nothing(?) is the most specific type for subtype, it doesn't bring valuable information to the user,
|
||||
// therefore it is discriminated in favor of supertype
|
||||
fun isSuitableResultedType(resultType: UnwrappedType): Boolean {
|
||||
return !resultType.isNothingOrNullableNothing()
|
||||
fun isSuitableResultedType(
|
||||
resultType: KotlinTypeMarker
|
||||
): Boolean {
|
||||
return !resultType.typeConstructor().isNothingConstructor()
|
||||
}
|
||||
|
||||
// It's possible to generate Nothing-like constraints inside incorporation mechanism:
|
||||
@@ -36,7 +39,7 @@ class TrivialConstraintTypeInferenceOracle {
|
||||
// Therefore, here we avoid adding such trivial constraints to have stable constraint system
|
||||
fun isGeneratedConstraintTrivial(
|
||||
otherConstraint: Constraint,
|
||||
generatedConstraintType: UnwrappedType
|
||||
generatedConstraintType: KotlinTypeMarker
|
||||
): Boolean {
|
||||
if (generatedConstraintType.isNothing()) return true
|
||||
|
||||
@@ -49,10 +52,13 @@ class TrivialConstraintTypeInferenceOracle {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
private fun KotlinTypeMarker.isNothingOrNullableNothing(): Boolean =
|
||||
typeConstructor().isNothingConstructor()
|
||||
|
||||
|
||||
private fun KotlinTypeMarker.containsOnlyNonNullableNothing(): Boolean =
|
||||
contains { it.isNothing() } && !contains { it.isNullableNothing() }
|
||||
|
||||
}
|
||||
|
||||
private fun UnwrappedType.isNothingOrNullableNothing(): Boolean =
|
||||
isNothing() || isNullableNothing()
|
||||
|
||||
private fun UnwrappedType.containsOnlyNonNullableNothing(): Boolean =
|
||||
contains { it.isNothing() } && !contains { it.isNullableNothing() }
|
||||
|
||||
+28
-23
@@ -18,24 +18,26 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||
import org.jetbrains.kotlin.types.model.freshTypeConstructor
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
|
||||
class TypeVariableDependencyInformationProvider(
|
||||
private val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>,
|
||||
private val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>,
|
||||
private val postponedKtPrimitives: List<PostponedResolvedAtom>,
|
||||
private val topLevelType: UnwrappedType?
|
||||
private val topLevelType: KotlinTypeMarker?,
|
||||
private val typeSystemContext: TypeSystemInferenceExtensionContext
|
||||
) {
|
||||
// not oriented edges
|
||||
private val constrainEdges: MutableMap<TypeConstructor, MutableSet<TypeConstructor>> = hashMapOf()
|
||||
private val constrainEdges: MutableMap<TypeConstructorMarker, MutableSet<TypeConstructorMarker>> = hashMapOf()
|
||||
|
||||
// oriented edges
|
||||
private val postponeArgumentsEdges: MutableMap<TypeConstructor, MutableSet<TypeConstructor>> = hashMapOf()
|
||||
private val postponeArgumentsEdges: MutableMap<TypeConstructorMarker, MutableSet<TypeConstructorMarker>> = hashMapOf()
|
||||
|
||||
private val relatedToAllOutputTypes: MutableSet<TypeConstructor> = hashSetOf()
|
||||
private val relatedToTopLevelType: MutableSet<TypeConstructor> = hashSetOf()
|
||||
private val relatedToAllOutputTypes: MutableSet<TypeConstructorMarker> = hashSetOf()
|
||||
private val relatedToTopLevelType: MutableSet<TypeConstructorMarker> = hashSetOf()
|
||||
|
||||
init {
|
||||
computeConstraintEdges()
|
||||
@@ -44,17 +46,17 @@ class TypeVariableDependencyInformationProvider(
|
||||
computeRelatedToTopLevelType()
|
||||
}
|
||||
|
||||
fun isVariableRelatedToTopLevelType(variable: TypeConstructor) = relatedToTopLevelType.contains(variable)
|
||||
fun isVariableRelatedToAnyOutputType(variable: TypeConstructor) = relatedToAllOutputTypes.contains(variable)
|
||||
fun isVariableRelatedToTopLevelType(variable: TypeConstructorMarker) = relatedToTopLevelType.contains(variable)
|
||||
fun isVariableRelatedToAnyOutputType(variable: TypeConstructorMarker) = relatedToAllOutputTypes.contains(variable)
|
||||
|
||||
private fun computeConstraintEdges() {
|
||||
fun addConstraintEdge(from: TypeConstructor, to: TypeConstructor) {
|
||||
fun addConstraintEdge(from: TypeConstructorMarker, to: TypeConstructorMarker) {
|
||||
constrainEdges.getOrPut(from) { hashSetOf() }.add(to)
|
||||
constrainEdges.getOrPut(to) { hashSetOf() }.add(from)
|
||||
}
|
||||
|
||||
for (variableWithConstraints in notFixedTypeVariables.values) {
|
||||
val from = variableWithConstraints.typeVariable.freshTypeConstructor
|
||||
val from = variableWithConstraints.typeVariable.freshTypeConstructor(typeSystemContext)
|
||||
|
||||
for (constraint in variableWithConstraints.constraints) {
|
||||
constraint.type.forAllMyTypeVariables {
|
||||
@@ -67,14 +69,14 @@ class TypeVariableDependencyInformationProvider(
|
||||
}
|
||||
|
||||
private fun computePostponeArgumentsEdges() {
|
||||
fun addPostponeArgumentsEdges(from: TypeConstructor, to: TypeConstructor) {
|
||||
fun addPostponeArgumentsEdges(from: TypeConstructorMarker, to: TypeConstructorMarker) {
|
||||
postponeArgumentsEdges.getOrPut(from) { hashSetOf() }.add(to)
|
||||
}
|
||||
|
||||
for (argument in postponedKtPrimitives) {
|
||||
if (argument.analyzed) continue
|
||||
|
||||
val typeVariablesInOutputType = SmartSet.create<TypeConstructor>()
|
||||
val typeVariablesInOutputType = SmartSet.create<TypeConstructorMarker>()
|
||||
(argument.outputType ?: continue).forAllMyTypeVariables { typeVariablesInOutputType.add(it) }
|
||||
if (typeVariablesInOutputType.isEmpty()) continue
|
||||
|
||||
@@ -104,18 +106,21 @@ class TypeVariableDependencyInformationProvider(
|
||||
}
|
||||
}
|
||||
|
||||
private fun isMyTypeVariable(typeConstructor: TypeConstructor) = notFixedTypeVariables.containsKey(typeConstructor)
|
||||
private fun isMyTypeVariable(typeConstructor: TypeConstructorMarker) = notFixedTypeVariables.containsKey(typeConstructor)
|
||||
|
||||
private fun UnwrappedType.forAllMyTypeVariables(action: (TypeConstructor) -> Unit) = this.contains {
|
||||
if (isMyTypeVariable(it.constructor)) action(it.constructor)
|
||||
private fun KotlinTypeMarker.forAllMyTypeVariables(action: (TypeConstructorMarker) -> Unit) =
|
||||
with(typeSystemContext) {
|
||||
contains {
|
||||
if (isMyTypeVariable(it.typeConstructor())) action(it.typeConstructor())
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
private fun getConstraintEdges(from: TypeConstructor): Set<TypeConstructor> = constrainEdges[from] ?: emptySet()
|
||||
private fun getPostponeEdges(from: TypeConstructor): Set<TypeConstructor> = postponeArgumentsEdges[from] ?: emptySet()
|
||||
private fun getConstraintEdges(from: TypeConstructorMarker): Set<TypeConstructorMarker> = constrainEdges[from] ?: emptySet()
|
||||
private fun getPostponeEdges(from: TypeConstructorMarker): Set<TypeConstructorMarker> = postponeArgumentsEdges[from] ?: emptySet()
|
||||
|
||||
private fun addAllRelatedNodes(to: MutableSet<TypeConstructor>, node: TypeConstructor, includePostponedEdges: Boolean) {
|
||||
private fun addAllRelatedNodes(to: MutableSet<TypeConstructorMarker>, node: TypeConstructorMarker, includePostponedEdges: Boolean) {
|
||||
if (to.add(node)) {
|
||||
for (relatedNode in getConstraintEdges(node)) {
|
||||
addAllRelatedNodes(to, relatedNode, includePostponedEdges)
|
||||
|
||||
+35
-29
@@ -20,12 +20,11 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom
|
||||
import org.jetbrains.kotlin.types.FlexibleType
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.checker.isIntersectionType
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.model.FlexibleTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariance
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
|
||||
|
||||
@@ -34,7 +33,7 @@ private typealias Variable = VariableWithConstraints
|
||||
class TypeVariableDirectionCalculator(
|
||||
private val c: VariableFixationFinder.Context,
|
||||
private val postponedKtPrimitives: List<PostponedResolvedAtom>,
|
||||
topLevelType: UnwrappedType
|
||||
topLevelType: KotlinTypeMarker
|
||||
) {
|
||||
enum class ResolveDirection {
|
||||
TO_SUBTYPE,
|
||||
@@ -55,7 +54,7 @@ class TypeVariableDirectionCalculator(
|
||||
fun getDirection(typeVariable: Variable): ResolveDirection =
|
||||
directions.getOrDefault(typeVariable, ResolveDirection.UNKNOWN)
|
||||
|
||||
private fun setupDirections(topReturnType: UnwrappedType) {
|
||||
private fun setupDirections(topReturnType: KotlinTypeMarker) {
|
||||
topReturnType.visitType(ResolveDirection.TO_SUBTYPE) { variableWithConstraints, direction ->
|
||||
enterToNode(variableWithConstraints, direction)
|
||||
}
|
||||
@@ -105,47 +104,54 @@ class TypeVariableDirectionCalculator(
|
||||
!(direction == ResolveDirection.TO_SUBTYPE && constraint.kind == ConstraintKind.UPPER) &&
|
||||
!(direction == ResolveDirection.TO_SUPERTYPE && constraint.kind == ConstraintKind.LOWER)
|
||||
|
||||
private fun UnwrappedType.visitType(
|
||||
private fun KotlinTypeMarker.visitType(
|
||||
startDirection: ResolveDirection,
|
||||
action: (variable: Variable, direction: ResolveDirection) -> Unit
|
||||
) =
|
||||
when (this) {
|
||||
is SimpleType -> visitType(startDirection, action)
|
||||
is FlexibleType -> {
|
||||
lowerBound.visitType(startDirection, action)
|
||||
upperBound.visitType(startDirection, action)
|
||||
) = when (this) {
|
||||
is SimpleTypeMarker -> visitType(startDirection, action)
|
||||
is FlexibleTypeMarker -> {
|
||||
with(c) {
|
||||
lowerBound().visitType(startDirection, action)
|
||||
upperBound().visitType(startDirection, action)
|
||||
}
|
||||
}
|
||||
else -> error("?!")
|
||||
}
|
||||
|
||||
private fun SimpleType.visitType(startDirection: ResolveDirection, action: (variable: Variable, direction: ResolveDirection) -> Unit) {
|
||||
if (isIntersectionType) {
|
||||
constructor.supertypes.forEach {
|
||||
it.unwrap().visitType(startDirection, action)
|
||||
private fun SimpleTypeMarker.visitType(
|
||||
startDirection: ResolveDirection,
|
||||
action: (variable: Variable, direction: ResolveDirection) -> Unit
|
||||
): Unit = with(c) {
|
||||
val constructor = typeConstructor()
|
||||
if (constructor.isIntersection()) {
|
||||
constructor.supertypes().forEach {
|
||||
it.visitType(startDirection, action)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (arguments.isEmpty()) {
|
||||
if (argumentsCount() == 0) {
|
||||
c.notFixedTypeVariables[constructor]?.let {
|
||||
action(it, startDirection)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val parameters = constructor.parameters
|
||||
if (parameters.size != arguments.size) return // incorrect type
|
||||
if (constructor.parametersCount() != argumentsCount()) return // incorrect type
|
||||
|
||||
for ((argument, parameter) in arguments.zip(parameters)) {
|
||||
if (argument.isStarProjection) continue
|
||||
for (index in 0 until constructor.parametersCount()) {
|
||||
val parameter = constructor.getParameter(index)
|
||||
val argument = getArgument(index)
|
||||
if (argument.isStarProjection()) continue
|
||||
|
||||
val variance = NewKotlinTypeChecker.effectiveVariance(parameter.variance, argument.projectionKind) ?: Variance.INVARIANT
|
||||
val variance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance()) ?: TypeVariance.INV
|
||||
val innerDirection = when (variance) {
|
||||
Variance.INVARIANT -> ResolveDirection.UNKNOWN
|
||||
Variance.OUT_VARIANCE -> startDirection
|
||||
Variance.IN_VARIANCE -> startDirection.opposite()
|
||||
TypeVariance.INV -> ResolveDirection.UNKNOWN
|
||||
TypeVariance.OUT -> startDirection
|
||||
TypeVariance.IN -> startDirection.opposite()
|
||||
}
|
||||
|
||||
argument.type.unwrap().visitType(innerDirection, action)
|
||||
argument.getType().visitType(innerDirection, action)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-18
@@ -20,30 +20,31 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintS
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtom
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
|
||||
class VariableFixationFinder(
|
||||
private val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
|
||||
) {
|
||||
interface Context {
|
||||
val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>
|
||||
val postponedTypeVariables: List<NewTypeVariable>
|
||||
interface Context : TypeSystemInferenceExtensionContext {
|
||||
val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
|
||||
val postponedTypeVariables: List<TypeVariableMarker>
|
||||
}
|
||||
|
||||
data class VariableForFixation(
|
||||
val variable: TypeConstructor,
|
||||
val variable: TypeConstructorMarker,
|
||||
val hasProperConstraint: Boolean,
|
||||
val hasOnlyTrivialProperConstraint: Boolean = false
|
||||
)
|
||||
|
||||
fun findFirstVariableForFixation(
|
||||
c: Context,
|
||||
allTypeVariables: List<TypeConstructor>,
|
||||
allTypeVariables: List<TypeConstructorMarker>,
|
||||
postponedKtPrimitives: List<PostponedResolvedAtom>,
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
topLevelType: UnwrappedType
|
||||
@@ -59,7 +60,7 @@ class VariableFixationFinder(
|
||||
}
|
||||
|
||||
private fun Context.getTypeVariableReadiness(
|
||||
variable: TypeConstructor,
|
||||
variable: TypeConstructorMarker,
|
||||
dependencyProvider: TypeVariableDependencyInformationProvider
|
||||
): TypeVariableFixationReadiness = when {
|
||||
!notFixedTypeVariables.contains(variable) ||
|
||||
@@ -72,13 +73,13 @@ class VariableFixationFinder(
|
||||
}
|
||||
|
||||
private fun Context.findTypeVariableForFixation(
|
||||
allTypeVariables: List<TypeConstructor>,
|
||||
allTypeVariables: List<TypeConstructorMarker>,
|
||||
postponedArguments: List<PostponedResolvedAtom>,
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
topLevelType: UnwrappedType
|
||||
topLevelType: KotlinTypeMarker
|
||||
): VariableForFixation? {
|
||||
val dependencyProvider = TypeVariableDependencyInformationProvider(
|
||||
notFixedTypeVariables, postponedArguments, topLevelType.takeIf { completionMode == PARTIAL }
|
||||
notFixedTypeVariables, postponedArguments, topLevelType.takeIf { completionMode == PARTIAL }, this
|
||||
)
|
||||
|
||||
val candidate = allTypeVariables.maxBy { getTypeVariableReadiness(it, dependencyProvider) } ?: return null
|
||||
@@ -94,29 +95,29 @@ class VariableFixationFinder(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Context.hasDependencyToOtherTypeVariables(typeVariable: TypeConstructor): Boolean {
|
||||
private fun Context.hasDependencyToOtherTypeVariables(typeVariable: TypeConstructorMarker): Boolean {
|
||||
for (constraint in notFixedTypeVariables[typeVariable]?.constraints ?: return false) {
|
||||
if (constraint.type.arguments.isNotEmpty() && constraint.type.contains { notFixedTypeVariables.containsKey(it.constructor) }) {
|
||||
if (constraint.type.lowerBoundIfFlexible().argumentsCount() != 0 && constraint.type.contains { notFixedTypeVariables.containsKey(it.typeConstructor()) }) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructor): Boolean {
|
||||
private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructorMarker): Boolean {
|
||||
return notFixedTypeVariables[variable]?.constraints?.all { constraint ->
|
||||
val isProperConstraint = isProperArgumentConstraint(constraint)
|
||||
isProperConstraint && trivialConstraintTypeInferenceOracle.isTrivialConstraint(constraint) || !isProperConstraint
|
||||
} ?: false
|
||||
}
|
||||
|
||||
private fun Context.variableHasProperArgumentConstraints(variable: TypeConstructor): Boolean =
|
||||
private fun Context.variableHasProperArgumentConstraints(variable: TypeConstructorMarker): Boolean =
|
||||
notFixedTypeVariables[variable]?.constraints?.any { isProperArgumentConstraint(it) } ?: false
|
||||
|
||||
private fun Context.isProperArgumentConstraint(c: Constraint) =
|
||||
isProperType(c.type) && c.position.initialConstraint.position !is DeclaredUpperBoundConstraintPosition
|
||||
|
||||
private fun Context.isProperType(type: UnwrappedType): Boolean =
|
||||
!type.contains { notFixedTypeVariables.containsKey(it.constructor) }
|
||||
private fun Context.isProperType(type: KotlinTypeMarker): Boolean =
|
||||
!type.contains { notFixedTypeVariables.containsKey(it.typeConstructor()) }
|
||||
|
||||
}
|
||||
+10
-8
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
|
||||
|
||||
sealed class ConstraintPosition
|
||||
@@ -48,7 +50,7 @@ class ReceiverConstraintPosition(val argument: KotlinCallArgument) : ConstraintP
|
||||
override fun toString() = "Receiver $argument"
|
||||
}
|
||||
|
||||
class FixVariableConstraintPosition(val variable: NewTypeVariable) : ConstraintPosition() {
|
||||
class FixVariableConstraintPosition(val variable: TypeVariableMarker) : ConstraintPosition() {
|
||||
override fun toString() = "Fix variable $variable"
|
||||
}
|
||||
|
||||
@@ -88,21 +90,21 @@ abstract class ConstraintSystemCallDiagnostic(applicability: ResolutionCandidate
|
||||
}
|
||||
|
||||
class NewConstraintError(
|
||||
val lowerType: UnwrappedType,
|
||||
val upperType: UnwrappedType,
|
||||
val lowerType: KotlinTypeMarker,
|
||||
val upperType: KotlinTypeMarker,
|
||||
val position: IncorporationConstraintPosition
|
||||
) : ConstraintSystemCallDiagnostic(if (position.from is ReceiverConstraintPosition) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE)
|
||||
|
||||
class CapturedTypeFromSubtyping(
|
||||
val typeVariable: NewTypeVariable,
|
||||
val constraintType: UnwrappedType,
|
||||
val typeVariable: TypeVariableMarker,
|
||||
val constraintType: KotlinTypeMarker,
|
||||
val position: ConstraintPosition
|
||||
) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
|
||||
|
||||
class NotEnoughInformationForTypeParameter(val typeVariable: NewTypeVariable) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
|
||||
class NotEnoughInformationForTypeParameter(val typeVariable: TypeVariableMarker) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
|
||||
|
||||
class ConstrainingTypeIsError(
|
||||
val typeVariable: NewTypeVariable,
|
||||
val constraintType: UnwrappedType,
|
||||
val typeVariable: TypeVariableMarker,
|
||||
val constraintType: KotlinTypeMarker,
|
||||
val position: IncorporationConstraintPosition
|
||||
) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
|
||||
+25
-21
@@ -5,13 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.model
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
|
||||
/**
|
||||
* Every type variable can be in the following states:
|
||||
@@ -36,24 +36,24 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
*/
|
||||
|
||||
interface ConstraintStorage {
|
||||
val allTypeVariables: Map<TypeConstructor, NewTypeVariable>
|
||||
val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints>
|
||||
val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
|
||||
val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
|
||||
val initialConstraints: List<InitialConstraint>
|
||||
val maxTypeDepthFromInitialConstraints: Int
|
||||
val errors: List<KotlinCallDiagnostic>
|
||||
val hasContradiction: Boolean
|
||||
val fixedTypeVariables: Map<TypeConstructor, UnwrappedType>
|
||||
val postponedTypeVariables: List<NewTypeVariable>
|
||||
val fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker>
|
||||
val postponedTypeVariables: List<TypeVariableMarker>
|
||||
|
||||
object Empty : ConstraintStorage {
|
||||
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable> get() = emptyMap()
|
||||
override val notFixedTypeVariables: Map<TypeConstructor, VariableWithConstraints> get() = emptyMap()
|
||||
override val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker> get() = emptyMap()
|
||||
override val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints> get() = emptyMap()
|
||||
override val initialConstraints: List<InitialConstraint> get() = emptyList()
|
||||
override val maxTypeDepthFromInitialConstraints: Int get() = 1
|
||||
override val errors: List<KotlinCallDiagnostic> get() = emptyList()
|
||||
override val hasContradiction: Boolean get() = false
|
||||
override val fixedTypeVariables: Map<TypeConstructor, UnwrappedType> get() = emptyMap()
|
||||
override val postponedTypeVariables: List<NewTypeVariable> get() = emptyList()
|
||||
override val fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker> get() = emptyMap()
|
||||
override val postponedTypeVariables: List<TypeVariableMarker> get() = emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ enum class ConstraintKind {
|
||||
|
||||
class Constraint(
|
||||
val kind: ConstraintKind,
|
||||
val type: UnwrappedType, // flexible types here is allowed
|
||||
val type: KotlinTypeMarker, // flexible types here is allowed
|
||||
val position: IncorporationConstraintPosition,
|
||||
val typeHashCode: Int = type.hashCode()
|
||||
) {
|
||||
@@ -93,13 +93,13 @@ class Constraint(
|
||||
}
|
||||
|
||||
interface VariableWithConstraints {
|
||||
val typeVariable: NewTypeVariable
|
||||
val typeVariable: TypeVariableMarker
|
||||
val constraints: List<Constraint>
|
||||
}
|
||||
|
||||
class InitialConstraint(
|
||||
val a: UnwrappedType,
|
||||
val b: UnwrappedType,
|
||||
val a: KotlinTypeMarker,
|
||||
val b: KotlinTypeMarker,
|
||||
val constraintKind: ConstraintKind, // see [checkConstraint]
|
||||
val position: ConstraintPosition
|
||||
) {
|
||||
@@ -114,13 +114,17 @@ class InitialConstraint(
|
||||
}
|
||||
}
|
||||
|
||||
fun InitialConstraint.checkConstraint(substitutor: TypeSubstitutor): Boolean {
|
||||
val newA = substitutor.substitute(a)
|
||||
val newB = substitutor.substitute(a)
|
||||
return checkConstraint(newB, constraintKind, newA)
|
||||
}
|
||||
//fun InitialConstraint.checkConstraint(substitutor: TypeSubstitutor): Boolean {
|
||||
// val newA = substitutor.substitute(a)
|
||||
// val newB = substitutor.substitute(b)
|
||||
// return checkConstraint(newB as KotlinTypeMarker, constraintKind, newA as KotlinTypeMarker)
|
||||
//}
|
||||
|
||||
fun checkConstraint(constraintType: KotlinTypeMarker, constraintKind: ConstraintKind, resultType: KotlinTypeMarker): Boolean {
|
||||
require(constraintType is UnwrappedType)
|
||||
require(resultType is UnwrappedType)
|
||||
|
||||
|
||||
fun checkConstraint(constraintType: UnwrappedType, constraintKind: ConstraintKind, resultType: UnwrappedType): Boolean {
|
||||
val typeChecker = KotlinTypeChecker.DEFAULT
|
||||
return when (constraintKind) {
|
||||
ConstraintKind.EQUALITY -> typeChecker.equalTypes(constraintType, resultType)
|
||||
|
||||
+8
-5
@@ -11,12 +11,15 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.LinkedHashMap
|
||||
|
||||
|
||||
class MutableVariableWithConstraints(
|
||||
override val typeVariable: NewTypeVariable,
|
||||
override val typeVariable: TypeVariableMarker,
|
||||
constraints: Collection<Constraint> = emptyList()
|
||||
) : VariableWithConstraints {
|
||||
override val constraints: List<Constraint>
|
||||
@@ -89,12 +92,12 @@ class MutableVariableWithConstraints(
|
||||
|
||||
|
||||
internal class MutableConstraintStorage : ConstraintStorage {
|
||||
override val allTypeVariables: MutableMap<TypeConstructor, NewTypeVariable> = LinkedHashMap()
|
||||
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints> = LinkedHashMap()
|
||||
override val allTypeVariables: MutableMap<TypeConstructorMarker, TypeVariableMarker> = LinkedHashMap()
|
||||
override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints> = LinkedHashMap()
|
||||
override val initialConstraints: MutableList<InitialConstraint> = ArrayList()
|
||||
override var maxTypeDepthFromInitialConstraints: Int = 1
|
||||
override val errors: MutableList<KotlinCallDiagnostic> = ArrayList()
|
||||
override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess }
|
||||
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType> = LinkedHashMap()
|
||||
override val postponedTypeVariables: ArrayList<NewTypeVariable> = ArrayList()
|
||||
override val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker> = LinkedHashMap()
|
||||
override val postponedTypeVariables: ArrayList<TypeVariableMarker> = ArrayList()
|
||||
}
|
||||
|
||||
+51
-46
@@ -6,24 +6,28 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.model
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.resolve.calls.components.BuiltInsProvider
|
||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.types.StubType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContext
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class NewConstraintSystemImpl(
|
||||
private val constraintInjector: ConstraintInjector,
|
||||
override val builtIns: KotlinBuiltIns
|
||||
val typeSystemContext: TypeSystemInferenceExtensionContext//,
|
||||
//override val builtIns: KotlinBuiltIns
|
||||
) :
|
||||
TypeSystemInferenceExtensionContext by typeSystemContext,
|
||||
NewConstraintSystem,
|
||||
ConstraintSystemBuilder,
|
||||
ConstraintInjector.Context,
|
||||
@@ -32,7 +36,7 @@ class NewConstraintSystemImpl(
|
||||
PostponedArgumentsAnalyzer.Context {
|
||||
private val storage = MutableConstraintStorage()
|
||||
private var state = State.BUILDING
|
||||
private val typeVariablesTransaction: MutableList<NewTypeVariable> = SmartList()
|
||||
private val typeVariablesTransaction: MutableList<TypeVariableMarker> = SmartList()
|
||||
|
||||
private enum class State {
|
||||
BUILDING,
|
||||
@@ -63,23 +67,23 @@ class NewConstraintSystemImpl(
|
||||
override fun asPostponedArgumentsAnalyzerContext() = apply { checkState(State.BUILDING) }
|
||||
|
||||
// ConstraintSystemOperation
|
||||
override fun registerVariable(variable: NewTypeVariable) {
|
||||
override fun registerVariable(variable: TypeVariableMarker) {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
|
||||
transactionRegisterVariable(variable)
|
||||
storage.allTypeVariables[variable.freshTypeConstructor] = variable
|
||||
storage.notFixedTypeVariables[variable.freshTypeConstructor] = MutableVariableWithConstraints(variable)
|
||||
storage.allTypeVariables[variable.freshTypeConstructor()] = variable
|
||||
storage.notFixedTypeVariables[variable.freshTypeConstructor()] = MutableVariableWithConstraints(variable)
|
||||
}
|
||||
|
||||
override fun markPostponedVariable(variable: NewTypeVariable) {
|
||||
override fun markPostponedVariable(variable: TypeVariableMarker) {
|
||||
storage.postponedTypeVariables += variable
|
||||
}
|
||||
|
||||
override fun unmarkPostponedVariable(variable: NewTypeVariable) {
|
||||
override fun unmarkPostponedVariable(variable: TypeVariableMarker) {
|
||||
storage.postponedTypeVariables -= variable
|
||||
}
|
||||
|
||||
override fun addSubtypeConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) =
|
||||
override fun addSubtypeConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) =
|
||||
constraintInjector.addInitialSubtypeConstraint(
|
||||
apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) },
|
||||
lowerType,
|
||||
@@ -87,7 +91,7 @@ class NewConstraintSystemImpl(
|
||||
position
|
||||
)
|
||||
|
||||
override fun addEqualityConstraint(a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) =
|
||||
override fun addEqualityConstraint(a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) =
|
||||
constraintInjector.addInitialEqualityConstraint(
|
||||
apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) },
|
||||
a,
|
||||
@@ -95,18 +99,18 @@ class NewConstraintSystemImpl(
|
||||
position
|
||||
)
|
||||
|
||||
override fun getProperSuperTypeConstructors(type: UnwrappedType): List<TypeConstructor> {
|
||||
override fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List<TypeConstructorMarker> {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
val variableWithConstraints = notFixedTypeVariables[type.constructor] ?: return listOf(type.constructor)
|
||||
val variableWithConstraints = notFixedTypeVariables[type.typeConstructor()] ?: return listOf(type.typeConstructor())
|
||||
|
||||
return variableWithConstraints.constraints.mapNotNull {
|
||||
if (it.kind == ConstraintKind.LOWER) return@mapNotNull null
|
||||
it.type.constructor.takeUnless { allTypeVariables.containsKey(it) }
|
||||
it.type.typeConstructor().takeUnless { allTypeVariables.containsKey(it) }
|
||||
}
|
||||
}
|
||||
|
||||
// ConstraintSystemBuilder
|
||||
private fun transactionRegisterVariable(variable: NewTypeVariable) {
|
||||
private fun transactionRegisterVariable(variable: TypeVariableMarker) {
|
||||
if (state != State.TRANSACTION) return
|
||||
typeVariablesTransaction.add(variable)
|
||||
}
|
||||
@@ -132,8 +136,8 @@ class NewConstraintSystemImpl(
|
||||
}
|
||||
|
||||
for (addedTypeVariable in typeVariablesTransaction) {
|
||||
storage.allTypeVariables.remove(addedTypeVariable.freshTypeConstructor)
|
||||
storage.notFixedTypeVariables.remove(addedTypeVariable.freshTypeConstructor)
|
||||
storage.allTypeVariables.remove(addedTypeVariable.freshTypeConstructor())
|
||||
storage.notFixedTypeVariables.remove(addedTypeVariable.freshTypeConstructor())
|
||||
}
|
||||
storage.maxTypeDepthFromInitialConstraints = beforeMaxTypeDepthFromInitialConstraints
|
||||
storage.errors.trimToSize(beforeErrorsCount)
|
||||
@@ -169,32 +173,32 @@ class NewConstraintSystemImpl(
|
||||
}
|
||||
storage.initialConstraints.addAll(otherSystem.initialConstraints)
|
||||
storage.maxTypeDepthFromInitialConstraints =
|
||||
Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints)
|
||||
Math.max(storage.maxTypeDepthFromInitialConstraints, otherSystem.maxTypeDepthFromInitialConstraints)
|
||||
storage.errors.addAll(otherSystem.errors)
|
||||
storage.fixedTypeVariables.putAll(otherSystem.fixedTypeVariables)
|
||||
storage.postponedTypeVariables.addAll(otherSystem.postponedTypeVariables)
|
||||
}
|
||||
|
||||
// ResultTypeResolver.Context, ConstraintSystemBuilder
|
||||
override fun isProperType(type: UnwrappedType): Boolean {
|
||||
override fun isProperType(type: KotlinTypeMarker): Boolean {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return !type.contains {
|
||||
storage.allTypeVariables.containsKey(it.constructor)
|
||||
storage.allTypeVariables.containsKey(it.typeConstructor())
|
||||
}
|
||||
}
|
||||
|
||||
override fun isTypeVariable(type: UnwrappedType): Boolean {
|
||||
override fun isTypeVariable(type: KotlinTypeMarker): Boolean {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return notFixedTypeVariables.containsKey(type.constructor)
|
||||
return notFixedTypeVariables.containsKey(type.typeConstructor())
|
||||
}
|
||||
|
||||
override fun isPostponedTypeVariable(typeVariable: NewTypeVariable): Boolean {
|
||||
override fun isPostponedTypeVariable(typeVariable: TypeVariableMarker): Boolean {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return typeVariable in postponedTypeVariables
|
||||
}
|
||||
|
||||
// ConstraintInjector.Context
|
||||
override val allTypeVariables: Map<TypeConstructor, NewTypeVariable>
|
||||
override val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
|
||||
get() {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return storage.allTypeVariables
|
||||
@@ -213,19 +217,19 @@ class NewConstraintSystemImpl(
|
||||
}
|
||||
|
||||
// ConstraintInjector.Context, FixationOrderCalculator.Context
|
||||
override val notFixedTypeVariables: MutableMap<TypeConstructor, MutableVariableWithConstraints>
|
||||
override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints>
|
||||
get() {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return storage.notFixedTypeVariables
|
||||
}
|
||||
|
||||
override val fixedTypeVariables: MutableMap<TypeConstructor, UnwrappedType>
|
||||
override val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker>
|
||||
get() {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return storage.fixedTypeVariables
|
||||
}
|
||||
|
||||
override val postponedTypeVariables: List<NewTypeVariable>
|
||||
override val postponedTypeVariables: List<TypeVariableMarker>
|
||||
get() {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
|
||||
return storage.postponedTypeVariables
|
||||
@@ -238,32 +242,32 @@ class NewConstraintSystemImpl(
|
||||
}
|
||||
|
||||
// KotlinConstraintSystemCompleter.Context
|
||||
override fun fixVariable(variable: NewTypeVariable, resultType: UnwrappedType) {
|
||||
override fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker) {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
|
||||
constraintInjector.addInitialEqualityConstraint(this, variable.defaultType, resultType, FixVariableConstraintPosition(variable))
|
||||
notFixedTypeVariables.remove(variable.freshTypeConstructor)
|
||||
constraintInjector.addInitialEqualityConstraint(this, variable.defaultType(), resultType, FixVariableConstraintPosition(variable))
|
||||
notFixedTypeVariables.remove(variable.freshTypeConstructor())
|
||||
|
||||
for (variableWithConstraint in notFixedTypeVariables.values) {
|
||||
variableWithConstraint.removeConstrains {
|
||||
it.type.contains { it.constructor == variable.freshTypeConstructor }
|
||||
it.type.contains { it.typeConstructor() == variable.freshTypeConstructor() }
|
||||
}
|
||||
}
|
||||
|
||||
storage.fixedTypeVariables[variable.freshTypeConstructor] = resultType
|
||||
storage.fixedTypeVariables[variable.freshTypeConstructor()] = resultType
|
||||
}
|
||||
|
||||
// KotlinConstraintSystemCompleter.Context, PostponedArgumentsAnalyzer.Context
|
||||
override fun canBeProper(type: UnwrappedType): Boolean {
|
||||
override fun canBeProper(type: KotlinTypeMarker): Boolean {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return !type.contains { storage.notFixedTypeVariables.containsKey(it.constructor) }
|
||||
return !type.contains { storage.notFixedTypeVariables.containsKey(it.typeConstructor()) }
|
||||
}
|
||||
|
||||
override fun containsOnlyFixedOrPostponedVariables(type: UnwrappedType): Boolean {
|
||||
override fun containsOnlyFixedOrPostponedVariables(type: KotlinTypeMarker): Boolean {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return !type.contains {
|
||||
val variable = storage.notFixedTypeVariables[it.constructor]?.typeVariable
|
||||
variable !in storage.postponedTypeVariables && storage.notFixedTypeVariables.containsKey(it.constructor)
|
||||
val variable = storage.notFixedTypeVariables[it.typeConstructor()]?.typeVariable
|
||||
variable !in storage.postponedTypeVariables && storage.notFixedTypeVariables.containsKey(it.typeConstructor())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,14 +277,15 @@ class NewConstraintSystemImpl(
|
||||
return buildCurrentSubstitutor(emptyMap())
|
||||
}
|
||||
|
||||
override fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructor, StubType>): NewTypeSubstitutor {
|
||||
override fun buildCurrentSubstitutor(additionalBindings: Map<TypeConstructorMarker, StubTypeMarker>): NewTypeSubstitutor {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return storage.buildCurrentSubstitutor(additionalBindings)
|
||||
}
|
||||
|
||||
override fun bindingStubsForPostponedVariables(): Map<NewTypeVariable, StubType> {
|
||||
override fun bindingStubsForPostponedVariables(): Map<TypeVariableMarker, StubTypeMarker> {
|
||||
checkState(State.BUILDING, State.COMPLETION)
|
||||
return storage.postponedTypeVariables.associate { it to StubType(it.freshTypeConstructor, it.defaultType.isMarkedNullable) }
|
||||
// TODO: SUB
|
||||
return storage.postponedTypeVariables.associate { it to createStubType(it)/*StubType(it.freshTypeConstructor() as TypeConstructor, it.defaultType().isMarkedNullable())*/ }
|
||||
}
|
||||
|
||||
override fun currentStorage(): ConstraintStorage {
|
||||
@@ -289,10 +294,10 @@ class NewConstraintSystemImpl(
|
||||
}
|
||||
|
||||
// PostponedArgumentsAnalyzer.Context
|
||||
override fun hasUpperOrEqualUnitConstraint(type: UnwrappedType): Boolean {
|
||||
override fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean {
|
||||
checkState(State.BUILDING, State.COMPLETION, State.FREEZED)
|
||||
|
||||
val constraints = storage.notFixedTypeVariables[type.constructor]?.constraints ?: return false
|
||||
val constraints = storage.notFixedTypeVariables[type.typeConstructor()]?.constraints ?: return false
|
||||
|
||||
return constraints.any { (it.kind == ConstraintKind.UPPER || it.kind == ConstraintKind.EQUALITY) && it.type.isUnit() }
|
||||
}
|
||||
|
||||
+2
-1
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
|
||||
|
||||
class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debugName: String) : TypeConstructor,
|
||||
@@ -42,7 +43,7 @@ class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debu
|
||||
override fun toString() = "TypeVariable($debugName)"
|
||||
}
|
||||
|
||||
sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) {
|
||||
sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) : TypeVariableMarker {
|
||||
val freshTypeConstructor: TypeConstructor = TypeVariableTypeConstructor(builtIns, name)
|
||||
|
||||
// member scope is used if we have receiver with type TypeVariable(T)
|
||||
|
||||
+1
-1
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.model
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
@@ -27,7 +28,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImp
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
|
||||
abstract class ResolutionPart {
|
||||
|
||||
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCa
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForTypeAliasObject
|
||||
import org.jetbrains.kotlin.resolve.calls.util.isLowPriorityFromStdlibJre7Or8
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasHidesMembersAnnotation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
@@ -135,7 +132,7 @@ internal class MemberScopeTowerLevel(
|
||||
private fun CallableDescriptor.approximateCapturedTypes(): CallableDescriptor {
|
||||
if (!isNewInferenceEnabled) return this
|
||||
|
||||
val approximator = TypeApproximator()
|
||||
val approximator = TypeApproximator(builtIns)
|
||||
val wrappedSubstitution = object : TypeSubstitution() {
|
||||
override fun get(key: KotlinType): TypeProjection? = null
|
||||
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = when (position) {
|
||||
|
||||
@@ -16,19 +16,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
|
||||
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.*
|
||||
import org.jetbrains.kotlin.types.checker.*
|
||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.types.model.CaptureStatus.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
|
||||
|
||||
|
||||
open class TypeApproximatorConfiguration {
|
||||
@@ -89,10 +89,8 @@ open class TypeApproximatorConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
class TypeApproximator {
|
||||
private val referenceApproximateToSuperType = this::approximateSimpleToSuperType
|
||||
private val referenceApproximateToSubType = this::approximateSimpleToSubType
|
||||
|
||||
class TypeApproximator(builtIns: KotlinBuiltIns) : AbstractTypeApproximator(ClassicTypeSystemContextForCS(builtIns)) {
|
||||
fun approximateDeclarationType(baseType: KotlinType, local: Boolean, languageVersionSettings: LanguageVersionSettings): UnwrappedType {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return baseType.unwrap()
|
||||
|
||||
@@ -103,49 +101,68 @@ class TypeApproximator {
|
||||
// null means that this input type is the result, i.e. input type not contains not-allowed kind of types
|
||||
// type <: resultType
|
||||
fun approximateToSuperType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
|
||||
approximateToSuperType(type, conf, -type.typeDepth())
|
||||
super.approximateToSuperType(type, conf) as UnwrappedType?
|
||||
|
||||
// resultType <: type
|
||||
fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
|
||||
super.approximateToSubType(type, conf) as UnwrappedType?
|
||||
}
|
||||
|
||||
abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionContext) : TypeSystemInferenceExtensionContext by ctx {
|
||||
|
||||
|
||||
private val referenceApproximateToSuperType = this::approximateSimpleToSuperType
|
||||
private val referenceApproximateToSubType = this::approximateSimpleToSubType
|
||||
|
||||
|
||||
|
||||
// null means that this input type is the result, i.e. input type not contains not-allowed kind of types
|
||||
// type <: resultType
|
||||
fun approximateToSuperType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration): KotlinTypeMarker? =
|
||||
approximateToSuperType(type, conf, -type.typeDepth())
|
||||
|
||||
// resultType <: type
|
||||
fun approximateToSubType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration): KotlinTypeMarker? =
|
||||
approximateToSubType(type, conf, -type.typeDepth())
|
||||
|
||||
private fun approximateToSuperType(type: UnwrappedType, conf: TypeApproximatorConfiguration, depth: Int): UnwrappedType? {
|
||||
private fun approximateToSuperType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, depth: Int): KotlinTypeMarker? {
|
||||
if (type is TypeUtils.SpecialType) return null
|
||||
return approximateTo(
|
||||
NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::upperBound,
|
||||
prepareType(type), conf, { upperBound() },
|
||||
referenceApproximateToSuperType, depth
|
||||
)
|
||||
}
|
||||
|
||||
private fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration, depth: Int): UnwrappedType? {
|
||||
private fun approximateToSubType(type: KotlinTypeMarker, conf: TypeApproximatorConfiguration, depth: Int): KotlinTypeMarker? {
|
||||
if (type is TypeUtils.SpecialType) return null
|
||||
return approximateTo(
|
||||
NewKotlinTypeChecker.transformToNewType(type), conf, FlexibleType::lowerBound,
|
||||
prepareType(type), conf, { lowerBound() },
|
||||
referenceApproximateToSubType, depth
|
||||
)
|
||||
}
|
||||
|
||||
// comments for case bound = upperBound, approximateTo = toSuperType
|
||||
private fun approximateTo(
|
||||
type: UnwrappedType,
|
||||
type: KotlinTypeMarker,
|
||||
conf: TypeApproximatorConfiguration,
|
||||
bound: FlexibleType.() -> SimpleType,
|
||||
approximateTo: (SimpleType, TypeApproximatorConfiguration, depth: Int) -> UnwrappedType?,
|
||||
bound: FlexibleTypeMarker.() -> SimpleTypeMarker,
|
||||
approximateTo: (SimpleTypeMarker, TypeApproximatorConfiguration, depth: Int) -> KotlinTypeMarker?,
|
||||
depth: Int
|
||||
): UnwrappedType? {
|
||||
): KotlinTypeMarker? {
|
||||
when (type) {
|
||||
is SimpleType -> return approximateTo(type, conf, depth)
|
||||
is FlexibleType -> {
|
||||
if (type is DynamicType) {
|
||||
is SimpleTypeMarker -> return approximateTo(type, conf, depth)
|
||||
is FlexibleTypeMarker -> {
|
||||
if (type.isDynamic()) {
|
||||
return if (conf.dynamic) null else type.bound()
|
||||
} else if (type is RawType) {
|
||||
} else if (type.asRawType() != null) {
|
||||
return if (conf.rawType) null else type.bound()
|
||||
}
|
||||
|
||||
// TODO: currently we can lose information about enhancement, should be fixed later
|
||||
assert(type is FlexibleTypeImpl || type is FlexibleTypeWithEnhancement) {
|
||||
"Unexpected subclass of FlexibleType: ${type::class.java.canonicalName}, type = $type"
|
||||
}
|
||||
// TODO: Restore check
|
||||
// // TODO: currently we can lose information about enhancement, should be fixed later
|
||||
// assert(type is FlexibleTypeImpl || type is FlexibleTypeWithEnhancement) {
|
||||
// "Unexpected subclass of FlexibleType: ${type::class.java.canonicalName}, type = $type"
|
||||
// }
|
||||
|
||||
if (conf.flexible) {
|
||||
/**
|
||||
@@ -158,8 +175,8 @@ class TypeApproximator {
|
||||
* I.e. for every type B such as L_2 <: B, L_1 <: B. For example B = L_2.
|
||||
*/
|
||||
|
||||
val lowerResult = approximateTo(type.lowerBound, conf, depth)
|
||||
val upperResult = approximateTo(type.upperBound, conf, depth)
|
||||
val lowerResult = approximateTo(type.lowerBound(), conf, depth)
|
||||
val upperResult = approximateTo(type.upperBound(), conf, depth)
|
||||
if (lowerResult == null && upperResult == null) return null
|
||||
|
||||
/**
|
||||
@@ -169,38 +186,39 @@ class TypeApproximator {
|
||||
*
|
||||
* If U_1 <: U_2.lower .. U_2.upper, then we know only that U_1 <: U_2.upper.
|
||||
*/
|
||||
return KotlinTypeFactory.flexibleType(
|
||||
lowerResult?.lowerIfFlexible() ?: type.lowerBound,
|
||||
upperResult?.upperIfFlexible() ?: type.upperBound
|
||||
return createFlexibleType(
|
||||
lowerResult?.lowerBoundIfFlexible() ?: type.lowerBound(),
|
||||
upperResult?.upperBoundIfFlexible() ?: type.upperBound()
|
||||
)
|
||||
} else {
|
||||
return type.bound().let { approximateTo(it, conf, depth) ?: it }
|
||||
}
|
||||
}
|
||||
else -> error("sealed")
|
||||
}
|
||||
}
|
||||
|
||||
private fun approximateIntersectionType(
|
||||
type: SimpleType,
|
||||
type: SimpleTypeMarker,
|
||||
conf: TypeApproximatorConfiguration,
|
||||
toSuper: Boolean,
|
||||
depth: Int
|
||||
): UnwrappedType? {
|
||||
val typeConstructor = type.constructor
|
||||
assert(typeConstructor is IntersectionTypeConstructor) {
|
||||
): KotlinTypeMarker? {
|
||||
val typeConstructor = type.typeConstructor()
|
||||
assert(typeConstructor.isIntersection()) {
|
||||
"Should be intersection type: $type, typeConstructor class: ${typeConstructor::class.java.canonicalName}"
|
||||
}
|
||||
assert(typeConstructor.supertypes.isNotEmpty()) {
|
||||
assert(typeConstructor.supertypes().isNotEmpty()) {
|
||||
"Supertypes for intersection type should not be empty: $type"
|
||||
}
|
||||
|
||||
var thereIsApproximation = false
|
||||
val newTypes = typeConstructor.supertypes.map {
|
||||
val newType = if (toSuper) approximateToSuperType(it.unwrap(), conf, depth) else approximateToSubType(it.unwrap(), conf, depth)
|
||||
val newTypes = typeConstructor.supertypes().map {
|
||||
val newType = if (toSuper) approximateToSuperType(it, conf, depth) else approximateToSubType(it, conf, depth)
|
||||
if (newType != null) {
|
||||
thereIsApproximation = true
|
||||
newType
|
||||
} else it.unwrap()
|
||||
} else it
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,12 +233,12 @@ class TypeApproximator {
|
||||
// commonSupertypeCalculator should handle flexible types correctly
|
||||
TO_COMMON_SUPERTYPE -> {
|
||||
if (!toSuper) return type.defaultResult(toSuper = false)
|
||||
val resultType = NewCommonSuperTypeCalculator.commonSuperType(newTypes)
|
||||
approximateToSuperType(resultType.unwrap(), conf) ?: resultType.unwrap()
|
||||
val resultType = with(NewCommonSuperTypeCalculator) { commonSuperType(newTypes) }
|
||||
approximateToSuperType(resultType, conf) ?: resultType
|
||||
}
|
||||
}
|
||||
|
||||
return if (type.isMarkedNullable) baseResult.makeNullableAsSpecified(true) else baseResult
|
||||
return if (type.isMarkedNullable()) baseResult.withNullability(true) else baseResult
|
||||
}
|
||||
|
||||
private fun approximateCapturedType(
|
||||
@@ -228,30 +246,30 @@ class TypeApproximator {
|
||||
conf: TypeApproximatorConfiguration,
|
||||
toSuper: Boolean,
|
||||
depth: Int
|
||||
): UnwrappedType? {
|
||||
val supertypes = type.constructor.supertypes
|
||||
): KotlinTypeMarker? {
|
||||
val supertypes = type.typeConstructor().supertypes()
|
||||
val baseSuperType = when (supertypes.size) {
|
||||
0 -> type.builtIns.nullableAnyType // Let C = in Int, then superType for C and C? is Any?
|
||||
1 -> supertypes.single()
|
||||
|
||||
// Consider the following example:
|
||||
// A.getA()::class.java, where `getA()` returns some class from Java
|
||||
// From `::class` we are getting type KClass<Cap<out A!>>, where Cap<out A!> have two supertypes:
|
||||
// - Any (from declared upper bound of type parameter for KClass)
|
||||
// - (A..A?) -- from A!, projection type of captured type
|
||||
// Consider the following example:
|
||||
// A.getA()::class.java, where `getA()` returns some class from Java
|
||||
// From `::class` we are getting type KClass<Cap<out A!>>, where Cap<out A!> have two supertypes:
|
||||
// - Any (from declared upper bound of type parameter for KClass)
|
||||
// - (A..A?) -- from A!, projection type of captured type
|
||||
|
||||
// Now, after approximation we were getting type `KClass<out A>`, because { Any & (A..A?) } = A,
|
||||
// but in old inference type was equal to `KClass<out A!>`.
|
||||
// Now, after approximation we were getting type `KClass<out A>`, because { Any & (A..A?) } = A,
|
||||
// but in old inference type was equal to `KClass<out A!>`.
|
||||
|
||||
// Important note that from the point of type system first type is more specific:
|
||||
// Here, approximation of KClass<Cap<out A!>> is a type KClass<T> such that KClass<Cap<out A!>> <: KClass<out T> =>
|
||||
// So, the the more specific type for T would be "some non-null (because of declared upper bound type) subtype of A", which is `out A`
|
||||
// Important note that from the point of type system first type is more specific:
|
||||
// Here, approximation of KClass<Cap<out A!>> is a type KClass<T> such that KClass<Cap<out A!>> <: KClass<out T> =>
|
||||
// So, the the more specific type for T would be "some non-null (because of declared upper bound type) subtype of A", which is `out A`
|
||||
|
||||
// But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass<out A!>`
|
||||
// But for now, to reduce differences in behaviour of old and new inference, we'll approximate such types to `KClass<out A!>`
|
||||
|
||||
// Once NI will be more stabilized, we'll use more specific type
|
||||
// Once NI will be more stabilized, we'll use more specific type
|
||||
|
||||
else -> type.constructor.projection.type.unwrap()
|
||||
else -> type.typeConstructorProjection().getType()//.unwrap()
|
||||
}
|
||||
val baseSubType = type.lowerType ?: type.builtIns.nothingType
|
||||
|
||||
@@ -276,32 +294,38 @@ class TypeApproximator {
|
||||
|
||||
// C = in Int, Int <: C => Int? <: C?
|
||||
// C = out Number, C <: Number => C? <: Number?
|
||||
return if (type.isMarkedNullable) baseResult.makeNullableAsSpecified(true) else baseResult
|
||||
return if (type.isMarkedNullable) baseResult.withNullability(true) else baseResult
|
||||
}
|
||||
|
||||
private fun approximateSimpleToSuperType(type: SimpleType, conf: TypeApproximatorConfiguration, depth: Int) =
|
||||
private fun approximateSimpleToSuperType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
|
||||
approximateTo(type, conf, toSuper = true, depth = depth)
|
||||
|
||||
private fun approximateSimpleToSubType(type: SimpleType, conf: TypeApproximatorConfiguration, depth: Int) =
|
||||
private fun approximateSimpleToSubType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
|
||||
approximateTo(type, conf, toSuper = false, depth = depth)
|
||||
|
||||
private fun approximateTo(type: SimpleType, conf: TypeApproximatorConfiguration, toSuper: Boolean, depth: Int): UnwrappedType? {
|
||||
if (type.isError) {
|
||||
private fun approximateTo(
|
||||
type: SimpleTypeMarker,
|
||||
conf: TypeApproximatorConfiguration,
|
||||
toSuper: Boolean,
|
||||
depth: Int
|
||||
): KotlinTypeMarker? {
|
||||
if (type.isError()) {
|
||||
// todo -- fix builtIns. Now builtIns here is DefaultBuiltIns
|
||||
return if (conf.errorType) null else type.defaultResult(toSuper)
|
||||
}
|
||||
|
||||
if (depth > 3) return type.defaultResult(toSuper)
|
||||
|
||||
if (type.arguments.isNotEmpty()) {
|
||||
if (type.argumentsCount() != 0) {
|
||||
return approximateParametrizedType(type, conf, toSuper, depth + 1)
|
||||
}
|
||||
|
||||
if (type is DefinitelyNotNullType) {
|
||||
return approximateDefinitelyNotNullType(type, conf, toSuper, depth)
|
||||
val definitelyNotNullType = type.asDefinitelyNotNullType()
|
||||
if (definitelyNotNullType != null) {
|
||||
return approximateDefinitelyNotNullType(definitelyNotNullType, conf, toSuper, depth)
|
||||
}
|
||||
|
||||
val typeConstructor = type.constructor
|
||||
val typeConstructor = type.typeConstructor()
|
||||
|
||||
if (typeConstructor is NewCapturedTypeConstructor) {
|
||||
assert(type is NewCapturedType) {
|
||||
@@ -312,7 +336,7 @@ class TypeApproximator {
|
||||
return approximateCapturedType(type as NewCapturedType, conf, toSuper, depth)
|
||||
}
|
||||
|
||||
if (typeConstructor is IntersectionTypeConstructor) {
|
||||
if (typeConstructor.isIntersection()) {
|
||||
return approximateIntersectionType(type, conf, toSuper, depth)
|
||||
}
|
||||
|
||||
@@ -320,9 +344,9 @@ class TypeApproximator {
|
||||
return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper)
|
||||
}
|
||||
|
||||
if (typeConstructor is IntegerLiteralTypeConstructor) {
|
||||
if (typeConstructor.isIntegerLiteralTypeConstructor()) {
|
||||
return if (conf.integerLiteralType)
|
||||
typeConstructor.getApproximatedType().unwrap().makeNullableAsSpecified(type.isMarkedNullable)
|
||||
typeConstructor.getApproximatedIntegerLiteralType().withNullability(type.isMarkedNullable())
|
||||
else
|
||||
null
|
||||
}
|
||||
@@ -331,63 +355,64 @@ class TypeApproximator {
|
||||
}
|
||||
|
||||
private fun approximateDefinitelyNotNullType(
|
||||
type: DefinitelyNotNullType,
|
||||
type: DefinitelyNotNullTypeMarker,
|
||||
conf: TypeApproximatorConfiguration,
|
||||
toSuper: Boolean,
|
||||
depth: Int
|
||||
): UnwrappedType? {
|
||||
val approximatedOriginalType = approximateTo(type.original, conf, toSuper, depth)
|
||||
): KotlinTypeMarker? {
|
||||
val approximatedOriginalType = approximateTo(type.original(), conf, toSuper, depth)
|
||||
return if (conf.definitelyNotNullType) {
|
||||
approximatedOriginalType?.makeDefinitelyNotNullOrNotNull()
|
||||
} else {
|
||||
if (toSuper)
|
||||
(approximatedOriginalType ?: type.original).makeNullableAsSpecified(false)
|
||||
(approximatedOriginalType ?: type.original()).withNullability(false)
|
||||
else
|
||||
type.defaultResult(toSuper)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isApproximateDirectionToSuper(effectiveVariance: Variance, toSuper: Boolean) =
|
||||
private fun isApproximateDirectionToSuper(effectiveVariance: TypeVariance, toSuper: Boolean) =
|
||||
when (effectiveVariance) {
|
||||
Variance.OUT_VARIANCE -> toSuper
|
||||
Variance.IN_VARIANCE -> !toSuper
|
||||
Variance.INVARIANT -> throw AssertionError("Incorrect variance $effectiveVariance")
|
||||
TypeVariance.OUT -> toSuper
|
||||
TypeVariance.IN -> !toSuper
|
||||
TypeVariance.INV -> throw AssertionError("Incorrect variance $effectiveVariance")
|
||||
}
|
||||
|
||||
private fun approximateParametrizedType(
|
||||
type: SimpleType,
|
||||
type: SimpleTypeMarker,
|
||||
conf: TypeApproximatorConfiguration,
|
||||
toSuper: Boolean,
|
||||
depth: Int
|
||||
): SimpleType? {
|
||||
val parameters = type.constructor.parameters
|
||||
val arguments = type.arguments
|
||||
if (parameters.size != arguments.size) {
|
||||
): SimpleTypeMarker? {
|
||||
val typeConstructor = type.typeConstructor()
|
||||
// val parameters = type.typeConstructor().parameters
|
||||
// val arguments = type.arguments
|
||||
if (typeConstructor.parametersCount() != type.argumentsCount()) {
|
||||
return if (conf.errorType) {
|
||||
ErrorUtils.createErrorType("Inconsistent type: $type (parameters.size = ${parameters.size}, arguments.size = ${arguments.size})")
|
||||
ErrorUtils.createErrorType("Inconsistent type: $type (parameters.size = ${typeConstructor.parametersCount()}, arguments.size = ${type.argumentsCount()})")
|
||||
} else type.defaultResult(toSuper)
|
||||
}
|
||||
|
||||
val newArguments = arrayOfNulls<TypeProjection?>(arguments.size)
|
||||
val newArguments = arrayOfNulls<TypeArgumentMarker?>(type.argumentsCount())
|
||||
|
||||
loop@ for (index in arguments.indices) {
|
||||
val parameter = parameters[index]
|
||||
val argument = arguments[index]
|
||||
loop@ for (index in 0 until type.argumentsCount()) {
|
||||
val parameter = typeConstructor.getParameter(index)
|
||||
val argument = type.getArgument(index)
|
||||
|
||||
if (argument.isStarProjection) continue
|
||||
if (argument.isStarProjection()) continue
|
||||
|
||||
val argumentType = argument.type.unwrap()
|
||||
val effectiveVariance = NewKotlinTypeChecker.effectiveVariance(parameter.variance, argument.projectionKind)
|
||||
val argumentType = argument.getType()//.unwrap()
|
||||
val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
||||
when (effectiveVariance) {
|
||||
null -> {
|
||||
return if (conf.errorType) {
|
||||
ErrorUtils.createErrorType(
|
||||
"Inconsistent type: $type ($index parameter has declared variance: ${parameter.variance}, " +
|
||||
"but argument variance is ${argument.projectionKind})"
|
||||
"Inconsistent type: $type ($index parameter has declared variance: ${parameter.getVariance()}, " +
|
||||
"but argument variance is ${argument.getVariance()})"
|
||||
)
|
||||
} else type.defaultResult(toSuper)
|
||||
}
|
||||
Variance.OUT_VARIANCE, Variance.IN_VARIANCE -> {
|
||||
TypeVariance.OUT, TypeVariance.IN -> {
|
||||
/**
|
||||
* Out<Foo> <: Out<superType(Foo)>
|
||||
* Inv<out Foo> <: Inv<out superType(Foo)>
|
||||
@@ -403,22 +428,27 @@ class TypeApproximator {
|
||||
}
|
||||
} ?: continue@loop
|
||||
|
||||
if (parameter.variance == Variance.INVARIANT) {
|
||||
newArguments[index] = TypeProjectionImpl(effectiveVariance, approximatedArgument)
|
||||
if (parameter.getVariance() == TypeVariance.INV) {
|
||||
newArguments[index] = createTypeArgument(approximatedArgument, effectiveVariance)
|
||||
} else {
|
||||
newArguments[index] = approximatedArgument.asTypeProjection()
|
||||
newArguments[index] = approximatedArgument.asTypeArgument()
|
||||
}
|
||||
}
|
||||
Variance.INVARIANT -> {
|
||||
TypeVariance.INV -> {
|
||||
if (!toSuper) {
|
||||
// Inv<Foo> cannot be approximated to subType
|
||||
val toSubType = approximateToSubType(argumentType, conf, depth) ?: continue@loop
|
||||
|
||||
// Inv<Foo!> is supertype for Inv<Foo?>
|
||||
if (!NewKotlinTypeChecker.equalTypes(argumentType, toSubType)) return type.defaultResult(toSuper)
|
||||
if (!AbstractTypeChecker.equalTypes(
|
||||
this,
|
||||
argumentType,
|
||||
toSubType
|
||||
)
|
||||
) return type.defaultResult(toSuper)
|
||||
|
||||
// also Captured(out Nothing) = Nothing
|
||||
newArguments[index] = toSubType.asTypeProjection()
|
||||
newArguments[index] = toSubType.asTypeArgument()
|
||||
continue@loop
|
||||
}
|
||||
|
||||
@@ -433,10 +463,10 @@ class TypeApproximator {
|
||||
* Note that for case Inv<C> we will chose Inv<in Int>, because it is more informative then Inv<out Any?>.
|
||||
* May be we should do the same for deeper types, but not now.
|
||||
*/
|
||||
if (argumentType.constructor is NewCapturedTypeConstructor) {
|
||||
if (argumentType.typeConstructor() is NewCapturedTypeConstructor) {
|
||||
val subType = approximateToSubType(argumentType, conf, depth) ?: continue@loop
|
||||
if (!subType.isTrivialSub()) {
|
||||
newArguments[index] = TypeProjectionImpl(Variance.IN_VARIANCE, subType)
|
||||
newArguments[index] = createTypeArgument(subType, TypeVariance.IN)
|
||||
continue@loop
|
||||
}
|
||||
}
|
||||
@@ -447,15 +477,15 @@ class TypeApproximator {
|
||||
val approximatedSubType =
|
||||
approximateToSubType(argumentType, conf, depth) ?: continue@loop // seems like this is never null
|
||||
if (!approximatedSubType.isTrivialSub()) {
|
||||
newArguments[index] = TypeProjectionImpl(Variance.IN_VARIANCE, approximatedSubType)
|
||||
newArguments[index] = createTypeArgument(approximatedSubType, TypeVariance.IN)
|
||||
continue@loop
|
||||
}
|
||||
}
|
||||
|
||||
if (NewKotlinTypeChecker.equalTypes(argumentType, approximatedSuperType)) {
|
||||
newArguments[index] = approximatedSuperType.asTypeProjection()
|
||||
if (AbstractTypeChecker.equalTypes(this, argumentType, approximatedSuperType)) {
|
||||
newArguments[index] = approximatedSuperType.asTypeArgument()
|
||||
} else {
|
||||
newArguments[index] = TypeProjectionImpl(Variance.OUT_VARIANCE, approximatedSuperType)
|
||||
newArguments[index] = createTypeArgument(approximatedSuperType, TypeVariance.OUT)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -463,33 +493,33 @@ class TypeApproximator {
|
||||
|
||||
if (newArguments.all { it == null }) return null
|
||||
|
||||
val newArgumentsList = arguments.mapIndexed { index, oldArgument -> newArguments[index] ?: oldArgument }
|
||||
return type.replace(newArgumentsList)
|
||||
val newArgumentsList = List(type.argumentsCount()) { index -> newArguments[index] ?: type.getArgument(index) }
|
||||
return type.replaceArguments(newArgumentsList)
|
||||
}
|
||||
|
||||
private fun SimpleType.defaultResult(toSuper: Boolean) = if (toSuper) builtIns.nullableAnyType else {
|
||||
if (isMarkedNullable) builtIns.nullableNothingType else builtIns.nothingType
|
||||
private fun SimpleTypeMarker.defaultResult(toSuper: Boolean) = if (toSuper) nullableAnyType() else {
|
||||
if (isMarkedNullable()) nullableNothingType() else nothingType()
|
||||
}
|
||||
|
||||
// Any? or Any!
|
||||
private fun UnwrappedType.isTrivialSuper() = upperIfFlexible().isNullableAny()
|
||||
private fun KotlinTypeMarker.isTrivialSuper() = upperBoundIfFlexible().isNullableAny()
|
||||
|
||||
// Nothing or Nothing!
|
||||
private fun UnwrappedType.isTrivialSub() = lowerIfFlexible().isNothing()
|
||||
}
|
||||
|
||||
internal fun UnwrappedType.typeDepth() =
|
||||
when (this) {
|
||||
is SimpleType -> typeDepth()
|
||||
is FlexibleType -> Math.max(lowerBound.typeDepth(), upperBound.typeDepth())
|
||||
}
|
||||
|
||||
internal fun SimpleType.typeDepth(): Int {
|
||||
if (this is TypeUtils.SpecialType) return 0
|
||||
|
||||
val maxInArguments = arguments.asSequence().map {
|
||||
if (it.isStarProjection) 1 else it.type.unwrap().typeDepth()
|
||||
}.max() ?: 0
|
||||
|
||||
return maxInArguments + 1
|
||||
private fun KotlinTypeMarker.isTrivialSub() = lowerBoundIfFlexible().isNothing()
|
||||
}
|
||||
//
|
||||
//internal fun KotlinTypeMarker.typeDepth() =
|
||||
// when (this) {
|
||||
// is SimpleTypeMarker -> typeDepth()
|
||||
// is FlexibleType -> Math.max(lowerBound.typeDepth(), upperBound.typeDepth())
|
||||
// }
|
||||
//
|
||||
//internal fun SimpleTypeMarker.typeDepth(): Int {
|
||||
// if (this is TypeUtils.SpecialType) return 0
|
||||
//
|
||||
// val maxInArguments = arguments.asSequence().map {
|
||||
// if (it.isStarProjection) 1 else it.type.unwrap().typeDepth()
|
||||
// }.max() ?: 0
|
||||
//
|
||||
// return maxInArguments + 1
|
||||
//}
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.types
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.types.model.StubTypeMarker
|
||||
|
||||
// This type is used as a stub for postponed type variables, which are important for coroutine inference
|
||||
class StubType(
|
||||
@@ -16,7 +17,7 @@ class StubType(
|
||||
ErrorUtils.createErrorTypeConstructor("Constructor for non fixed type: $originalTypeVariable"),
|
||||
override val memberScope: MemberScope =
|
||||
ErrorUtils.createErrorScope("Scope for non fixed type: $originalTypeVariable")
|
||||
) : SimpleType() {
|
||||
) : SimpleType(), StubTypeMarker {
|
||||
|
||||
override val arguments: List<TypeProjection>
|
||||
get() = emptyList()
|
||||
|
||||
+16
-16
@@ -24,13 +24,9 @@ import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
|
||||
open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowedTypeVariable: Boolean = true) : ClassicTypeSystemContext, AbstractTypeCheckerContext() {
|
||||
override fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return org.jetbrains.kotlin.types.checker.intersectTypes(types as List<UnwrappedType>)
|
||||
}
|
||||
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return super.prepareType(transformToNewType((type as KotlinType).unwrap()))
|
||||
return transformToNewType((type as KotlinType).unwrap())
|
||||
}
|
||||
|
||||
override val isErrorTypeEqualsToAnything: Boolean
|
||||
@@ -54,22 +50,26 @@ open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val
|
||||
}
|
||||
|
||||
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
|
||||
require(type is SimpleType, type::errorMessage)
|
||||
return classicSubstitutionSupertypePolicy(type)
|
||||
}
|
||||
|
||||
val substitutor = TypeConstructorSubstitution.create(type).buildSubstitutor()
|
||||
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean get() = this is UnwrappedType && allowedTypeVariable && constructor is NewTypeVariableConstructor
|
||||
|
||||
return object : SupertypesPolicy.DoCustomTransform() {
|
||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker {
|
||||
return substitutor.safeSubstitute(
|
||||
type.lowerBoundIfFlexible() as KotlinType,
|
||||
Variance.INVARIANT
|
||||
).asSimpleType()!!
|
||||
companion object {
|
||||
fun ClassicTypeSystemContext.classicSubstitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
|
||||
require(type is SimpleType, type::errorMessage)
|
||||
val substitutor = TypeConstructorSubstitution.create(type).buildSubstitutor()
|
||||
|
||||
return object : SupertypesPolicy.DoCustomTransform() {
|
||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker {
|
||||
return substitutor.safeSubstitute(
|
||||
type.lowerBoundIfFlexible() as KotlinType,
|
||||
Variance.INVARIANT
|
||||
).asSimpleType()!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean get() = this is UnwrappedType && allowedTypeVariable && constructor is NewTypeVariableConstructor
|
||||
}
|
||||
|
||||
private fun Any.errorMessage(): String {
|
||||
|
||||
+246
-1
@@ -8,14 +8,18 @@ package org.jetbrains.kotlin.types.checker
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
|
||||
interface ClassicTypeSystemContext : TypeSystemContext {
|
||||
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
||||
override fun TypeConstructorMarker.isDenotable(): Boolean {
|
||||
require(this is TypeConstructor, this::errorMessage)
|
||||
return this.isDenotable
|
||||
@@ -134,6 +138,13 @@ interface ClassicTypeSystemContext : TypeSystemContext {
|
||||
}
|
||||
|
||||
|
||||
private fun TypeVariance.convertVariance(): Variance {
|
||||
return when (this) {
|
||||
TypeVariance.INV -> Variance.INVARIANT
|
||||
TypeVariance.IN -> Variance.IN_VARIANCE
|
||||
TypeVariance.OUT -> Variance.OUT_VARIANCE
|
||||
}
|
||||
}
|
||||
|
||||
override fun TypeArgumentMarker.getType(): KotlinTypeMarker {
|
||||
require(this is TypeProjection, this::errorMessage)
|
||||
@@ -220,6 +231,11 @@ interface ClassicTypeSystemContext : TypeSystemContext {
|
||||
return this.asTypeProjection()
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isUnitTypeConstructor(): Boolean {
|
||||
require(this is TypeConstructor, this::errorMessage)
|
||||
return KotlinBuiltIns.isTypeConstructorForGivenClass(this, FQ_NAMES.unit)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* SingleClassifierType is one of the following types:
|
||||
@@ -240,6 +256,231 @@ interface ClassicTypeSystemContext : TypeSystemContext {
|
||||
require(this is KotlinType, this::errorMessage)
|
||||
return typeConstructor().isNothingConstructor() && !TypeUtils.isNullableType(this)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.contains(predicate: (KotlinTypeMarker) -> Boolean): Boolean {
|
||||
require(this is KotlinType, this::errorMessage)
|
||||
return containsInternal(this, predicate)
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.typeDepth(): Int {
|
||||
require(this is SimpleType, this::errorMessage)
|
||||
return this.typeDepthInternal()
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.typeDepth(): Int {
|
||||
require(this is UnwrappedType, this::errorMessage)
|
||||
return this.typeDepthInternal()
|
||||
}
|
||||
|
||||
override fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return org.jetbrains.kotlin.types.checker.intersectTypes(types as List<UnwrappedType>)
|
||||
}
|
||||
|
||||
override fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return org.jetbrains.kotlin.types.checker.intersectTypes(types as List<SimpleType>)
|
||||
}
|
||||
|
||||
override fun Collection<KotlinTypeMarker>.singleBestRepresentative(): KotlinTypeMarker? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return singleBestRepresentative(this as Collection<KotlinType>)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isUnit(): Boolean {
|
||||
require(this is UnwrappedType, this::errorMessage)
|
||||
return KotlinBuiltIns.isUnit(this)
|
||||
}
|
||||
|
||||
override fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker {
|
||||
require(lowerBound is SimpleType, this::errorMessage)
|
||||
require(upperBound is SimpleType, this::errorMessage)
|
||||
return KotlinTypeFactory.flexibleType(lowerBound, upperBound)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker {
|
||||
return when (this) {
|
||||
is SimpleTypeMarker -> this.withNullability(nullable)
|
||||
is FlexibleTypeMarker -> createFlexibleType(lowerBound().withNullability(nullable), upperBound().withNullability(nullable))
|
||||
else -> error("sealed")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun newBaseTypeCheckerContext(errorTypesEqualToAnything: Boolean): AbstractTypeCheckerContext {
|
||||
return ClassicTypeCheckerContext(errorTypesEqualToAnything)
|
||||
}
|
||||
|
||||
override fun nullableNothingType(): SimpleTypeMarker {
|
||||
return builtIns.nullableNothingType
|
||||
}
|
||||
|
||||
override fun nullableAnyType(): SimpleTypeMarker {
|
||||
return builtIns.nullableAnyType
|
||||
}
|
||||
|
||||
override fun nothingType(): SimpleTypeMarker {
|
||||
return builtIns.nothingType
|
||||
}
|
||||
|
||||
val builtIns: KotlinBuiltIns get() = throw UnsupportedOperationException("Not supported")
|
||||
|
||||
override fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker {
|
||||
require(this is UnwrappedType, this::errorMessage)
|
||||
return makeDefinitelyNotNullOrNotNullInternal(this)
|
||||
}
|
||||
|
||||
|
||||
override fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker {
|
||||
require(this is SimpleType, this::errorMessage)
|
||||
return makeSimpleTypeDefinitelyNotNullOrNotNullInternal(this)
|
||||
}
|
||||
|
||||
|
||||
override fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker {
|
||||
require(this is UnwrappedType, this::errorMessage)
|
||||
return this.replaceAnnotations(Annotations.EMPTY)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.hasExactAnnotation(): Boolean {
|
||||
require(this is UnwrappedType, this::errorMessage)
|
||||
return hasExactInternal(this)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.hasNoInferAnnotation(): Boolean {
|
||||
require(this is UnwrappedType, this::errorMessage)
|
||||
return hasNoInferInternal(this)
|
||||
}
|
||||
|
||||
override fun TypeVariableMarker.freshTypeConstructor(): TypeConstructorMarker {
|
||||
errorSupportedOnlyInTypeInference()
|
||||
}
|
||||
|
||||
override fun CapturedTypeMarker.typeConstructorProjection(): TypeArgumentMarker {
|
||||
require(this is NewCapturedType, this::errorMessage)
|
||||
return this.constructor.projection
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isNullableType(): Boolean {
|
||||
require(this is KotlinType, this::errorMessage)
|
||||
return TypeUtils.isNullableType(this)
|
||||
}
|
||||
|
||||
override fun createSimpleType(
|
||||
constructor: TypeConstructorMarker,
|
||||
arguments: List<TypeArgumentMarker>,
|
||||
nullable: Boolean
|
||||
): SimpleTypeMarker {
|
||||
require(constructor is TypeConstructor, constructor::errorMessage)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return KotlinTypeFactory.simpleType(Annotations.EMPTY, constructor, arguments as List<TypeProjection>, nullable)
|
||||
}
|
||||
|
||||
override fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker {
|
||||
require(type is KotlinType, type::errorMessage)
|
||||
return TypeProjectionImpl(variance.convertVariance(), type)
|
||||
}
|
||||
|
||||
override fun createStarProjection(typeParameter: TypeParameterMarker): TypeArgumentMarker {
|
||||
require(typeParameter is TypeParameterDescriptor, typeParameter::errorMessage)
|
||||
return StarProjectionImpl(typeParameter)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean {
|
||||
require(this is UnwrappedType, this::errorMessage)
|
||||
return constructor is NewTypeVariableConstructor ||
|
||||
constructor.declarationDescriptor is TypeParameterDescriptor ||
|
||||
this is NewCapturedType
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.replaceArguments(newArguments: List<TypeArgumentMarker>): SimpleTypeMarker {
|
||||
require(this is SimpleType, this::errorMessage)
|
||||
return this.replace(newArguments as List<TypeProjection>)
|
||||
}
|
||||
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
require(type is UnwrappedType, type::errorMessage)
|
||||
return NewKotlinTypeChecker.transformToNewType(type)
|
||||
}
|
||||
|
||||
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker {
|
||||
require(this is DefinitelyNotNullType, this::errorMessage)
|
||||
return this.original
|
||||
}
|
||||
|
||||
override fun createCapturedType(
|
||||
constructorProjection: TypeArgumentMarker,
|
||||
constructorSupertypes: List<KotlinTypeMarker>,
|
||||
lowerType: KotlinTypeMarker?,
|
||||
captureStatus: CaptureStatus
|
||||
): CapturedTypeMarker {
|
||||
errorSupportedOnlyInTypeInference()
|
||||
}
|
||||
|
||||
override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker {
|
||||
errorSupportedOnlyInTypeInference()
|
||||
}
|
||||
|
||||
override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
errorSupportedOnlyInTypeInference()
|
||||
}
|
||||
|
||||
override fun TypeVariableMarker.defaultType(): SimpleTypeMarker {
|
||||
errorSupportedOnlyInTypeInference()
|
||||
}
|
||||
|
||||
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker {
|
||||
errorSupportedOnlyInTypeInference()
|
||||
}
|
||||
|
||||
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
explicitSupertypes as List<SimpleType>
|
||||
return IntegerLiteralTypeConstructor.findCommonSuperType(explicitSupertypes)
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker {
|
||||
require(this is IntegerLiteralTypeConstructor, this::errorMessage)
|
||||
return this.getApproximatedType().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasNoInferInternal(type: UnwrappedType): Boolean {
|
||||
return type.hasNoInferAnnotation()
|
||||
}
|
||||
|
||||
|
||||
private fun hasExactInternal(type: UnwrappedType): Boolean {
|
||||
return type.hasExactAnnotation()
|
||||
}
|
||||
|
||||
|
||||
private fun makeDefinitelyNotNullOrNotNullInternal(type: UnwrappedType): UnwrappedType {
|
||||
return type.makeDefinitelyNotNullOrNotNull()
|
||||
}
|
||||
|
||||
private fun makeSimpleTypeDefinitelyNotNullOrNotNullInternal(type: SimpleType): SimpleType {
|
||||
return type.makeSimpleTypeDefinitelyNotNullOrNotNull()
|
||||
}
|
||||
|
||||
private fun containsInternal(type: KotlinType, predicate: (KotlinTypeMarker) -> Boolean): Boolean = type.contains(predicate)
|
||||
|
||||
private fun singleBestRepresentative(collection: Collection<KotlinType>) = collection.singleBestRepresentative()
|
||||
|
||||
internal fun UnwrappedType.typeDepthInternal() =
|
||||
when (this) {
|
||||
is SimpleType -> typeDepthInternal()
|
||||
is FlexibleType -> Math.max(lowerBound.typeDepthInternal(), upperBound.typeDepthInternal())
|
||||
}
|
||||
|
||||
internal fun SimpleType.typeDepthInternal(): Int {
|
||||
if (this is TypeUtils.SpecialType) return 0
|
||||
|
||||
val maxInArguments = arguments.asSequence().map {
|
||||
if (it.isStarProjection) 1 else it.type.unwrap().typeDepthInternal()
|
||||
}.max() ?: 0
|
||||
|
||||
return maxInArguments + 1
|
||||
}
|
||||
|
||||
|
||||
@@ -248,6 +489,10 @@ private inline fun Any.errorMessage(): String {
|
||||
return "ClassicTypeSystemContext couldn't handle: $this, ${this::class}"
|
||||
}
|
||||
|
||||
private fun errorSupportedOnlyInTypeInference(): Nothing {
|
||||
error("supported only in type inference context")
|
||||
}
|
||||
|
||||
fun Variance.convertVariance(): TypeVariance {
|
||||
return when (this) {
|
||||
Variance.INVARIANT -> TypeVariance.INV
|
||||
|
||||
@@ -30,20 +30,21 @@ import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
object SimpleClassicTypeSystemContext : ClassicTypeSystemContext
|
||||
|
||||
object StrictEqualityTypeChecker {
|
||||
|
||||
private val context = object : ClassicTypeSystemContext {}
|
||||
/**
|
||||
* String! != String & A<String!> != A<String>, also A<in Nothing> != A<out Any?>
|
||||
* also A<*> != A<out Any?>
|
||||
* different error types non-equals even errorTypeEqualToAnything
|
||||
*/
|
||||
fun strictEqualTypes(a: UnwrappedType, b: UnwrappedType): Boolean {
|
||||
return AbstractStrictEqualityTypeChecker.strictEqualTypes(context, a, b)
|
||||
return AbstractStrictEqualityTypeChecker.strictEqualTypes(SimpleClassicTypeSystemContext, a, b)
|
||||
}
|
||||
|
||||
fun strictEqualTypes(a: SimpleType, b: SimpleType): Boolean {
|
||||
return AbstractStrictEqualityTypeChecker.strictEqualTypes(context, a, b)
|
||||
return AbstractStrictEqualityTypeChecker.strictEqualTypes(SimpleClassicTypeSystemContext, a, b)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,11 +65,11 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
|
||||
ClassicTypeCheckerContext(false).equalTypes(a.unwrap(), b.unwrap())
|
||||
|
||||
fun ClassicTypeCheckerContext.equalTypes(a: UnwrappedType, b: UnwrappedType): Boolean {
|
||||
return AbstractTypeChecker.equalTypes(this, a, b)
|
||||
return AbstractTypeChecker.equalTypes(this as AbstractTypeCheckerContext, a, b)
|
||||
}
|
||||
|
||||
fun ClassicTypeCheckerContext.isSubtypeOf(subType: UnwrappedType, superType: UnwrappedType): Boolean {
|
||||
return AbstractTypeChecker.isSubtypeOf(this, subType, superType)
|
||||
return AbstractTypeChecker.isSubtypeOf(this as AbstractTypeCheckerContext, subType, superType)
|
||||
}
|
||||
|
||||
fun transformToNewType(type: SimpleType): SimpleType {
|
||||
@@ -156,10 +157,9 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
|
||||
object NullabilityChecker {
|
||||
|
||||
fun isSubtypeOfAny(type: UnwrappedType): Boolean =
|
||||
ClassicTypeCheckerContext(false).hasNotNullSupertype(type.lowerIfFlexible(), SupertypesPolicy.LowerIfFlexible)
|
||||
|
||||
fun hasPathByNotMarkedNullableNodes(start: SimpleType, end: TypeConstructor) =
|
||||
ClassicTypeCheckerContext(false).hasPathByNotMarkedNullableNodes(start, end)
|
||||
SimpleClassicTypeSystemContext
|
||||
.newBaseTypeCheckerContext(false)
|
||||
.hasNotNullSupertype(type.lowerIfFlexible(), SupertypesPolicy.LowerIfFlexible)
|
||||
}
|
||||
|
||||
fun UnwrappedType.hasSupertypeWithGivenTypeConstructor(typeConstructor: TypeConstructor) =
|
||||
|
||||
@@ -21,9 +21,7 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
||||
|
||||
abstract fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean
|
||||
|
||||
abstract fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker
|
||||
|
||||
open fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return type
|
||||
}
|
||||
|
||||
@@ -146,6 +144,15 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
||||
}
|
||||
|
||||
object AbstractTypeChecker {
|
||||
|
||||
fun isSubtypeOf(context: TypeCheckerProviderContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
|
||||
return AbstractTypeChecker.isSubtypeOf(context.newBaseTypeCheckerContext(true), subType, superType)
|
||||
}
|
||||
|
||||
fun equalTypes(context: TypeCheckerProviderContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean {
|
||||
return AbstractTypeChecker.equalTypes(context.newBaseTypeCheckerContext(false), a, b)
|
||||
}
|
||||
|
||||
fun isSubtypeOf(context: AbstractTypeCheckerContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
|
||||
if (subType === superType) return true
|
||||
return context.completeIsSubTypeOf(context.prepareType(subType), context.prepareType(superType))
|
||||
@@ -312,7 +319,7 @@ object AbstractTypeChecker {
|
||||
!type.isDynamic() && !type.isDefinitelyNotNullType() &&
|
||||
type.lowerBoundIfFlexible().typeConstructor() == type.upperBoundIfFlexible().typeConstructor()
|
||||
|
||||
private fun effectiveVariance(declared: TypeVariance, useSite: TypeVariance): TypeVariance? {
|
||||
fun effectiveVariance(declared: TypeVariance, useSite: TypeVariance): TypeVariance? {
|
||||
if (declared == TypeVariance.INV) return useSite
|
||||
if (useSite == TypeVariance.INV) return declared
|
||||
|
||||
@@ -453,6 +460,14 @@ object AbstractNullabilityChecker {
|
||||
fun isPossibleSubtype(context: AbstractTypeCheckerContext, subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean =
|
||||
context.runIsPossibleSubtype(subType, superType)
|
||||
|
||||
fun isSubtypeOfAny(context: TypeCheckerProviderContext, type: KotlinTypeMarker): Boolean =
|
||||
AbstractNullabilityChecker.isSubtypeOfAny(context.newBaseTypeCheckerContext(false), type)
|
||||
|
||||
fun isSubtypeOfAny(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): Boolean =
|
||||
with(context) {
|
||||
hasNotNullSupertype(type.lowerBoundIfFlexible(), SupertypesPolicy.LowerIfFlexible)
|
||||
}
|
||||
|
||||
private fun AbstractTypeCheckerContext.runIsPossibleSubtype(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean {
|
||||
// it makes for case String? & Any <: String
|
||||
assert(subType.isSingleClassifierType() || subType.typeConstructor().isIntersection() || subType.isAllowedTypeVariable) {
|
||||
@@ -501,6 +516,9 @@ object AbstractNullabilityChecker {
|
||||
if (it.isMarkedNullable()) SupertypesPolicy.None else supertypesPolicy
|
||||
}
|
||||
|
||||
fun TypeCheckerProviderContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
|
||||
newBaseTypeCheckerContext(false).hasPathByNotMarkedNullableNodes(start, end)
|
||||
|
||||
fun AbstractTypeCheckerContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
|
||||
anySupertype(start, {
|
||||
it.isNotNullNothing() || (!it.isMarkedNullable() && isEqualTypeConstructors(it.typeConstructor(), end))
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types.model
|
||||
|
||||
fun TypeVariableMarker.freshTypeConstructor(c: TypeSystemInferenceExtensionContext) = with(c) { freshTypeConstructor() }
|
||||
fun TypeSubstitutorMarker.safeSubstitute(
|
||||
c: TypeSystemInferenceExtensionContext,
|
||||
type: KotlinTypeMarker
|
||||
) = with(c) { safeSubstitute(type) }
|
||||
|
||||
fun TypeVariableMarker.defaultType(c: TypeSystemInferenceExtensionContext) = with(c) { defaultType() }
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.types.model
|
||||
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
|
||||
interface KotlinTypeMarker
|
||||
interface TypeArgumentMarker
|
||||
interface TypeConstructorMarker
|
||||
@@ -17,14 +19,21 @@ interface DefinitelyNotNullTypeMarker : SimpleTypeMarker
|
||||
interface FlexibleTypeMarker : KotlinTypeMarker
|
||||
interface DynamicTypeMarker : FlexibleTypeMarker
|
||||
interface RawTypeMarker : FlexibleTypeMarker
|
||||
interface StubTypeMarker : SimpleTypeMarker
|
||||
|
||||
interface TypeArgumentListMarker
|
||||
|
||||
interface TypeVariableMarker
|
||||
|
||||
enum class TypeVariance {
|
||||
IN,
|
||||
OUT,
|
||||
INV
|
||||
interface TypeSubstitutorMarker
|
||||
|
||||
|
||||
enum class TypeVariance(val presentation: String) {
|
||||
IN("in"),
|
||||
OUT("out"),
|
||||
INV("");
|
||||
|
||||
override fun toString(): String = presentation
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +44,96 @@ interface TypeSystemOptimizationContext {
|
||||
fun identicalArguments(a: SimpleTypeMarker, b: SimpleTypeMarker) = false
|
||||
}
|
||||
|
||||
interface TypeSystemBuiltInsContext {
|
||||
fun nullableNothingType(): SimpleTypeMarker
|
||||
fun nullableAnyType(): SimpleTypeMarker
|
||||
fun nothingType(): SimpleTypeMarker
|
||||
}
|
||||
|
||||
interface TypeSystemTypeFactoryContext {
|
||||
fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker
|
||||
fun createSimpleType(constructor: TypeConstructorMarker, arguments: List<TypeArgumentMarker>, nullable: Boolean): SimpleTypeMarker
|
||||
fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker
|
||||
fun createStarProjection(typeParameter: TypeParameterMarker): TypeArgumentMarker
|
||||
}
|
||||
|
||||
|
||||
interface TypeCheckerProviderContext {
|
||||
fun newBaseTypeCheckerContext(errorTypesEqualToAnything: Boolean): AbstractTypeCheckerContext
|
||||
}
|
||||
|
||||
interface TypeSystemCommonSuperTypesContext : TypeSystemContext, TypeSystemTypeFactoryContext, TypeCheckerProviderContext {
|
||||
|
||||
fun KotlinTypeMarker.anySuperTypeConstructor(predicate: (TypeConstructorMarker) -> Boolean) =
|
||||
newBaseTypeCheckerContext(false).anySupertype(lowerBoundIfFlexible(), {
|
||||
predicate(it.typeConstructor())
|
||||
}, { AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible })
|
||||
|
||||
fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean
|
||||
|
||||
fun SimpleTypeMarker.typeDepth(): Int
|
||||
fun KotlinTypeMarker.typeDepth(): Int
|
||||
|
||||
fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker?
|
||||
}
|
||||
|
||||
interface TypeSystemInferenceExtensionContextDelegate : TypeSystemInferenceExtensionContext
|
||||
|
||||
interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBuiltInsContext, TypeSystemCommonSuperTypesContext {
|
||||
fun KotlinTypeMarker.contains(predicate: (KotlinTypeMarker) -> Boolean): Boolean
|
||||
|
||||
fun TypeConstructorMarker.isUnitTypeConstructor(): Boolean
|
||||
|
||||
fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker
|
||||
|
||||
fun Collection<KotlinTypeMarker>.singleBestRepresentative(): KotlinTypeMarker?
|
||||
|
||||
fun KotlinTypeMarker.isUnit(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker
|
||||
|
||||
|
||||
fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker
|
||||
fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker
|
||||
|
||||
fun createCapturedType(
|
||||
constructorProjection: TypeArgumentMarker,
|
||||
constructorSupertypes: List<KotlinTypeMarker>,
|
||||
lowerType: KotlinTypeMarker?,
|
||||
captureStatus: CaptureStatus
|
||||
): CapturedTypeMarker
|
||||
|
||||
fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker
|
||||
|
||||
|
||||
fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker
|
||||
|
||||
fun SimpleTypeMarker.replaceArguments(newArguments: List<TypeArgumentMarker>): SimpleTypeMarker
|
||||
|
||||
fun KotlinTypeMarker.hasExactAnnotation(): Boolean
|
||||
fun KotlinTypeMarker.hasNoInferAnnotation(): Boolean
|
||||
|
||||
fun TypeVariableMarker.freshTypeConstructor(): TypeConstructorMarker
|
||||
|
||||
|
||||
fun CapturedTypeMarker.typeConstructorProjection(): TypeArgumentMarker
|
||||
|
||||
fun KotlinTypeMarker.isNullableType(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.isNullableAny() = this.typeConstructor().isAnyConstructor() && this.isNullableType()
|
||||
fun KotlinTypeMarker.isNothing() = this.typeConstructor().isNothingConstructor() && !this.isNullableType()
|
||||
fun KotlinTypeMarker.isNullableNothing() = this.typeConstructor().isNothingConstructor() && this.isNullableType()
|
||||
|
||||
fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker
|
||||
|
||||
fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker
|
||||
|
||||
fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker
|
||||
|
||||
|
||||
fun TypeVariableMarker.defaultType(): SimpleTypeMarker
|
||||
}
|
||||
|
||||
|
||||
class ArgumentList(initialSize: Int) : ArrayList<TypeArgumentMarker>(initialSize), TypeArgumentListMarker
|
||||
|
||||
@@ -53,6 +152,8 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
||||
fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker
|
||||
fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker?
|
||||
|
||||
fun KotlinTypeMarker.isCapturedType() = asSimpleType()?.asCapturedType() != null
|
||||
|
||||
fun SimpleTypeMarker.asDefinitelyNotNullType(): DefinitelyNotNullTypeMarker?
|
||||
fun SimpleTypeMarker.isMarkedNullable(): Boolean
|
||||
fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker
|
||||
@@ -66,7 +167,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
||||
return null
|
||||
}
|
||||
|
||||
fun SimpleTypeMarker.isStubType(): Boolean = false
|
||||
fun SimpleTypeMarker.isStubType(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.asTypeArgument(): TypeArgumentMarker
|
||||
|
||||
@@ -150,6 +251,13 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
||||
* Such types can contains error types in our arguments, but type constructor isn't errorTypeConstructor
|
||||
*/
|
||||
fun SimpleTypeMarker.isSingleClassifierType(): Boolean
|
||||
|
||||
fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker
|
||||
fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker
|
||||
|
||||
fun KotlinTypeMarker.isSimpleType() = asSimpleType() != null
|
||||
|
||||
fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker
|
||||
}
|
||||
|
||||
enum class CaptureStatus {
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
val BackendContext.externalSymbols: ReferenceSymbolTable get() = ir.symbols.externalSymbolTable
|
||||
|
||||
internal fun BackendContext.createTypeTranslator(moduleDescriptor: ModuleDescriptor): TypeTranslator =
|
||||
TypeTranslator(externalSymbols, irBuiltIns.languageVersionSettings).apply {
|
||||
TypeTranslator(externalSymbols, irBuiltIns.languageVersionSettings, moduleDescriptor.builtIns).apply {
|
||||
constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable = externalSymbols)
|
||||
constantValueGenerator.typeTranslator = this
|
||||
}
|
||||
|
||||
+2
-1
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||
import org.jetbrains.kotlin.type.MapPsiToAsmDesc
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.isInterface
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.uast.*
|
||||
@@ -232,7 +233,7 @@ internal fun KotlinType.toPsiType(lightDeclaration: PsiModifierListOwner?, conte
|
||||
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
||||
val typeMappingMode = if (boxed) TypeMappingMode.GENERIC_ARGUMENT else TypeMappingMode.DEFAULT
|
||||
val approximatedType = TypeApproximator().approximateDeclarationType(this, true, languageVersionSettings)
|
||||
val approximatedType = TypeApproximator(this.builtIns).approximateDeclarationType(this, true, languageVersionSettings)
|
||||
typeMapper.mapType(approximatedType, signatureWriter, typeMappingMode)
|
||||
|
||||
val signature = StringCharacterIterator(signatureWriter.toString())
|
||||
|
||||
Reference in New Issue
Block a user