[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:
+33
-15
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user