From 915ac32bfbd84fbf62e5387902b1946d6a865519 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Fri, 9 Jun 2017 15:59:12 +0300 Subject: [PATCH] [NI] Improve type inference for T vs Captured(in Smt) If we has Inv <: Inv then we should get: - T <: Captured(in Foo) - Captured(in Foo) <: T Before this commit we got: T <: Foo instead first constraint. --- .../TypeCheckerContextForConstraintSystem.kt | 7 +++++-- .../kotlin/types/checker/NewKotlinTypeChecker.kt | 11 +++++------ .../kotlin/types/checker/TypeCheckerContext.kt | 8 +++++++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt index ac50e77b753..973b4d06796 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerContextForConstraintSystem.kt @@ -29,8 +29,11 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT abstract fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType) abstract fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType) - override fun shouldCheckOnlyLowerBoundForCapturedType(subType: SimpleType, superType: NewCapturedType) = - subType.contains { it.anyBound(this::isMyTypeVariable) } + override fun getLowerCapturedTypePolicy(subType: SimpleType, superType: NewCapturedType) = when { + isMyTypeVariable(subType) -> LowerCapturedTypePolicy.SKIP_LOWER + subType.contains { it.anyBound(this::isMyTypeVariable) } -> LowerCapturedTypePolicy.CHECK_ONLY_LOWER + else -> LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER + } /** * todo: possible we should override this method, because otherwise OR in subtyping transformed to AND in constraint system diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt index 257763f1d52..ef9ad3c67af 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewKotlinTypeChecker.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.CapturedType import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructor import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.TypeCheckerContext.LowerCapturedTypePolicy.* import org.jetbrains.kotlin.types.checker.TypeCheckerContext.SeveralSupertypesWithSameConstructorPolicy.* import org.jetbrains.kotlin.types.checker.TypeCheckerContext.SupertypesPolicy import org.jetbrains.kotlin.types.typeUtil.asTypeProjection @@ -160,12 +161,10 @@ object NewKotlinTypeChecker : KotlinTypeChecker { } if (superType is NewCapturedType && superType.lowerType != null) { - val subtypeOfLowerType = isSubtypeOf(subType, superType.lowerType) - if (shouldCheckOnlyLowerBoundForCapturedType(subType, superType)) { - return subtypeOfLowerType - } - else if (subtypeOfLowerType) { - return true + when (getLowerCapturedTypePolicy(subType, superType)) { + CHECK_ONLY_LOWER -> return isSubtypeOf(subType, superType.lowerType) + CHECK_SUBTYPE_AND_LOWER -> if(isSubtypeOf(subType, superType.lowerType)) return true + SKIP_LOWER -> { /*do nothing*/ } } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/TypeCheckerContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/TypeCheckerContext.kt index 4d6b239becd..d089e17a892 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/TypeCheckerContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/TypeCheckerContext.kt @@ -33,7 +33,7 @@ open class TypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowe return a == b } - open fun shouldCheckOnlyLowerBoundForCapturedType(subType: SimpleType, superType: NewCapturedType): Boolean = false + open fun getLowerCapturedTypePolicy(subType: SimpleType, superType: NewCapturedType) = LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER open val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.INTERSECT_ARGUMENTS_AND_CHECK_AGAIN internal inline fun runWithArgumentsSettings(subArgument: UnwrappedType, f: TypeCheckerContext.() -> T): T { @@ -127,5 +127,11 @@ open class TypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowe INTERSECT_ARGUMENTS_AND_CHECK_AGAIN } + enum class LowerCapturedTypePolicy { + CHECK_ONLY_LOWER, + CHECK_SUBTYPE_AND_LOWER, + SKIP_LOWER + } + val UnwrappedType.isAllowedTypeVariable: Boolean get() = allowedTypeVariable && constructor is NewTypeVariableConstructor } \ No newline at end of file