[NI] Add constrains even we try add constraint like TypeVariable <: CapturedType from subtyping.

If such captured type has lower type, then from TypeVariable <: lowerType => TypeVariable <: CapturedType.
This commit is contained in:
Stanislav Erokhin
2017-04-07 13:24:34 +03:00
parent 657c332a1f
commit 53caa84db9
6 changed files with 67 additions and 34 deletions
@@ -16,19 +16,17 @@
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.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.FlexibleType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.CaptureStatus
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.contains
import java.util.*
class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator) {
class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val typeApproximator: TypeApproximator) {
private val ALLOWED_DEPTH_DELTA_FOR_INCORPORATION = 3
interface Context {
@@ -119,24 +117,44 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator) {
override fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType) =
addConstraint(typeVariable, subType, ConstraintKind.LOWER)
private fun isCapturedTypeFromSubtyping(type: UnwrappedType) =
when ((type as? NewCapturedType)?.captureStatus) {
null, CaptureStatus.FROM_EXPRESSION -> false
CaptureStatus.FOR_SUBTYPING -> true
CaptureStatus.FOR_INCORPORATION ->
error("Captured type for incorporation shouldn't escape from incorporation: $type\n" + renderBaseConstraint())
}
private fun addConstraint(typeVariableConstructor: TypeConstructor, type: UnwrappedType, kind: ConstraintKind) {
val typeVariable = c.allTypeVariables[typeVariableConstructor]
?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}")
if (type.contains {
val captureStatus = (it as? NewCapturedType)?.captureStatus
assert(captureStatus != CaptureStatus.FOR_INCORPORATION) {
"Captured type for incorporation shouldn't escape from incorporation: $type\n" + renderBaseConstraint()
var targetType = type
if (type.contains(this::isCapturedTypeFromSubtyping)) {
// TypeVariable <: type -> if TypeVariable <: subType => TypeVariable <: type
if (kind == ConstraintKind.UPPER) {
val subType = typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
if (subType != null && !KotlinBuiltIns.isNothingOrNullableNothing(subType)) {
targetType = subType
}
}
if (kind == ConstraintKind.LOWER) {
val superType = typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.SubtypeCapturedTypesApproximation)
if (superType != null && !KotlinBuiltIns.isAnyOrNullableAny(superType)) { // todo rethink error reporting for Any cases
targetType = superType
}
}
if (targetType === type) {
c.addError(CapturedTypeFromSubtyping(typeVariable, type, position))
return
}
captureStatus != null && captureStatus != CaptureStatus.FROM_EXPRESSION
}) {
c.addError(CapturedTypeFromSubtyping(typeVariable, type, position))
return
}
if (!c.isAllowedType(type)) return
if (!c.isAllowedType(targetType)) return
val newConstraint = Constraint(kind, type, position)
val newConstraint = Constraint(kind, targetType, position)
possibleNewConstraints.add(typeVariable to newConstraint)
}
@@ -19,12 +19,8 @@ package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.resolve.calls.components.CommonSupertypeCalculator
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.*
import org.jetbrains.kotlin.types.checker.CaptureStatus.FOR_INCORPORATION
import org.jetbrains.kotlin.types.checker.CaptureStatus.FROM_EXPRESSION
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.checker.intersectTypes
import org.jetbrains.kotlin.types.checker.*
import org.jetbrains.kotlin.types.checker.CaptureStatus.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.isNothing
@@ -64,24 +60,18 @@ open class TypeApproximatorConfiguration {
override val allFlexible get() = true
}
object IncorporationConfiguration : TypeApproximatorConfiguration.AllFlexibleSameValue() {
abstract class AbstractCapturedTypesApproximation(val approximatedCapturedStatus: CaptureStatus): TypeApproximatorConfiguration.AllFlexibleSameValue() {
override val allFlexible get() = true
// i.e. will be approximated only FOR_INCORPORATION captured types
override val capturedType get() = { it: NewCapturedType -> it.captureStatus != FOR_INCORPORATION }
override val intersection get() = IntersectionStrategy.ALLOWED
override val typeVariable: (TypeVariableTypeConstructor) -> Boolean get() = { true }
}
object CapturedTypesApproximation : TypeApproximatorConfiguration.AllFlexibleSameValue() {
override val allFlexible get() = true
// i.e. will be approximated only FROM_EXPRESSION captured types
override val capturedType get() = { it: NewCapturedType -> it.captureStatus != FROM_EXPRESSION }
// i.e. will be approximated only approximatedCapturedStatus captured types
override val capturedType get() = { it: NewCapturedType -> it.captureStatus != approximatedCapturedStatus }
override val intersection get() = IntersectionStrategy.ALLOWED
override val typeVariable: (TypeVariableTypeConstructor) -> Boolean get() = { true }
}
object IncorporationConfiguration : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FOR_INCORPORATION)
object SubtypeCapturedTypesApproximation : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FOR_SUBTYPING)
object CapturedTypesApproximation : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FROM_EXPRESSION)
}
class TypeApproximator(private val commonSupertypeCalculator: CommonSupertypeCalculator) {