Implement inferring materialized self types through a default type in ResultTypeResolver
This commit is contained in:
@@ -177,6 +177,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
||||
return this.typeArguments.getOrNull(index) ?: ConeStarProjection
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.getArguments(): List<TypeArgumentMarker> {
|
||||
require(this is ConeKotlinType)
|
||||
return this.typeArguments.toList()
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.asTypeArgument(): TypeArgumentMarker {
|
||||
require(this is ConeKotlinType)
|
||||
return this
|
||||
|
||||
@@ -116,6 +116,12 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
||||
error("Type $this has no arguments")
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.getArguments(): List<TypeArgumentMarker> =
|
||||
when (this) {
|
||||
is IrSimpleType -> arguments
|
||||
else -> error("Type $this has no arguments")
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.asTypeArgument() = this as IrTypeArgument
|
||||
|
||||
override fun CapturedTypeMarker.lowerType(): KotlinTypeMarker? = (this as IrCapturedType).lowerType
|
||||
|
||||
+22
-7
@@ -5,9 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
|
||||
fun ConstraintStorage.buildCurrentSubstitutor(
|
||||
@@ -49,10 +47,27 @@ fun ConstraintStorage.buildNotFixedVariablesToNonSubtypableTypesSubstitutor(
|
||||
)
|
||||
}
|
||||
|
||||
fun TypeSystemInferenceExtensionContext.hasDeclaredUpperBoundSelfTypes(constraint: Constraint): Boolean {
|
||||
val typeConstructor = constraint.type.typeConstructor()
|
||||
fun TypeSystemInferenceExtensionContext.hasRecursiveTypeParametersWithGivenSelfType(selfTypeConstructor: TypeConstructorMarker) =
|
||||
selfTypeConstructor.getParameters().any { it.hasRecursiveBounds(selfTypeConstructor) }
|
||||
|
||||
return constraint.position.from is DeclaredUpperBoundConstraintPosition<*>
|
||||
&& (typeConstructor.getParameters().any { it.hasRecursiveBounds(typeConstructor) }
|
||||
|| typeConstructor.getTypeParameterClassifier()?.hasRecursiveBounds() == true)
|
||||
fun TypeSystemInferenceExtensionContext.isRecursiveTypeParameter(typeConstructor: TypeConstructorMarker) =
|
||||
typeConstructor.getTypeParameterClassifier()?.hasRecursiveBounds() == true
|
||||
|
||||
fun TypeSystemInferenceExtensionContext.extractTypeForGivenRecursiveTypeParameter(
|
||||
type: KotlinTypeMarker,
|
||||
typeParameter: TypeParameterMarker
|
||||
): KotlinTypeMarker? {
|
||||
for (argument in type.getArguments()) {
|
||||
if (argument.isStarProjection()) continue
|
||||
val typeConstructor = argument.getType().typeConstructor()
|
||||
if (typeConstructor is TypeVariableTypeConstructorMarker
|
||||
&& typeConstructor.typeParameter == typeParameter
|
||||
&& typeConstructor.typeParameter?.hasRecursiveBounds(type.typeConstructor()) == true
|
||||
) {
|
||||
return type
|
||||
}
|
||||
extractTypeForGivenRecursiveTypeParameter(argument.getType(), typeParameter)?.let { return it }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import kotlin.math.max
|
||||
class ConstraintInjector(
|
||||
val constraintIncorporator: ConstraintIncorporator,
|
||||
val typeApproximator: AbstractTypeApproximator,
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
) {
|
||||
private val ALLOWED_DEPTH_DELTA_FOR_INCORPORATION = 1
|
||||
|
||||
|
||||
+30
-12
@@ -5,11 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
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.inference.components.TypeVariableDirectionCalculator.ResolveDirection
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.hasDeclaredUpperBoundSelfTypes
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.extractTypeForGivenRecursiveTypeParameter
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
@@ -27,13 +26,36 @@ class ResultTypeResolver(
|
||||
fun isReified(variable: TypeVariableMarker): Boolean
|
||||
}
|
||||
|
||||
private fun Context.getDefaultTypeForSelfType(
|
||||
constraints: List<Constraint>,
|
||||
typeVariable: TypeVariableMarker
|
||||
): KotlinTypeMarker? {
|
||||
val typeVariableConstructor = typeVariable.freshTypeConstructor() as TypeVariableTypeConstructorMarker
|
||||
val typesForRecursiveTypeParameters = constraints.mapNotNull { constraint ->
|
||||
if (constraint.position.from !is DeclaredUpperBoundConstraintPosition<*>) return@mapNotNull null
|
||||
val typeParameter = typeVariableConstructor.typeParameter ?: return@mapNotNull null
|
||||
extractTypeForGivenRecursiveTypeParameter(constraint.type, typeParameter)
|
||||
}.takeIf { it.isNotEmpty() } ?: return null
|
||||
|
||||
return createCapturedStarProjectionForSelfType(typeVariableConstructor, typesForRecursiveTypeParameters)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun Context.getDefaultType(
|
||||
direction: ResolveDirection,
|
||||
constraints: List<Constraint>,
|
||||
typeVariable: TypeVariableMarker
|
||||
): KotlinTypeMarker {
|
||||
getDefaultTypeForSelfType(constraints, typeVariable)?.let { return it }
|
||||
|
||||
return if (direction == ResolveDirection.TO_SUBTYPE) nothingType() else nullableAnyType()
|
||||
}
|
||||
|
||||
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker {
|
||||
findResultTypeOrNull(c, variableWithConstraints, direction)?.let { return it }
|
||||
|
||||
// no proper constraints
|
||||
return run {
|
||||
if (direction == ResolveDirection.TO_SUBTYPE) c.nothingType() else c.nullableAnyType()
|
||||
}
|
||||
return c.getDefaultType(direction, variableWithConstraints.constraints, variableWithConstraints.typeVariable)
|
||||
}
|
||||
|
||||
private fun findResultTypeOrNull(
|
||||
@@ -214,12 +236,8 @@ class ResultTypeResolver(
|
||||
}
|
||||
|
||||
private fun Context.findSuperType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
|
||||
val isTypeInferenceForSelfTypesSupported =
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.TypeInferenceOnCallsWithSelfTypes)
|
||||
val upperConstraints = variableWithConstraints.constraints.filter {
|
||||
it.kind == ConstraintKind.UPPER
|
||||
&& ((isTypeInferenceForSelfTypesSupported && hasDeclaredUpperBoundSelfTypes(it)) || isProperTypeForFixation(it.type))
|
||||
}
|
||||
val upperConstraints =
|
||||
variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && this@findSuperType.isProperTypeForFixation(it.type) }
|
||||
if (upperConstraints.isNotEmpty()) {
|
||||
val intersectionUpperType = intersectTypes(upperConstraints.map { it.type })
|
||||
val resultIsActuallyIntersection = intersectionUpperType.typeConstructor().isIntersection()
|
||||
@@ -246,7 +264,7 @@ class ResultTypeResolver(
|
||||
|
||||
return typeApproximator.approximateToSubType(
|
||||
upperType,
|
||||
TypeApproximatorConfiguration.InternalAndSelfTypesApproximation
|
||||
TypeApproximatorConfiguration.InternalTypesApproximation
|
||||
) ?: upperType
|
||||
}
|
||||
return null
|
||||
|
||||
+9
-4
@@ -8,7 +8,8 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode.PARTIAL
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.hasDeclaredUpperBoundSelfTypes
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.hasRecursiveTypeParametersWithGivenSelfType
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.isRecursiveTypeParameter
|
||||
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.VariableWithConstraints
|
||||
@@ -66,7 +67,7 @@ class VariableFixationFinder(
|
||||
): TypeVariableFixationReadiness = when {
|
||||
!notFixedTypeVariables.contains(variable) ||
|
||||
dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN
|
||||
isTypeInferenceForSelfTypesSupported && hasDeclaredUpperBoundSelfTypes(variable) ->
|
||||
isTypeInferenceForSelfTypesSupported && hasOnlyDeclaredUpperBoundSelfTypes(variable) ->
|
||||
TypeVariableFixationReadiness.READY_FOR_FIXATION_DECLARED_UPPER_BOUND_WITH_SELF_TYPES
|
||||
!variableHasProperArgumentConstraints(variable) -> TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT
|
||||
hasDependencyToOtherTypeVariables(variable) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY
|
||||
@@ -174,9 +175,13 @@ class VariableFixationFinder(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Context.hasDeclaredUpperBoundSelfTypes(variable: TypeConstructorMarker): Boolean {
|
||||
private fun Context.hasOnlyDeclaredUpperBoundSelfTypes(variable: TypeConstructorMarker): Boolean {
|
||||
val constraints = notFixedTypeVariables[variable]?.constraints ?: return false
|
||||
return constraints.isNotEmpty() && constraints.all(::hasDeclaredUpperBoundSelfTypes)
|
||||
return constraints.isNotEmpty() && constraints.all {
|
||||
val typeConstructor = it.type.typeConstructor()
|
||||
it.position.from is DeclaredUpperBoundConstraintPosition<*>
|
||||
&& (hasRecursiveTypeParametersWithGivenSelfType(typeConstructor) || isRecursiveTypeParameter(typeConstructor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -404,17 +404,6 @@ abstract class AbstractTypeApproximator(
|
||||
|
||||
if (argument.isStarProjection()) continue
|
||||
|
||||
val argumentTypeConstructor = argument.getType().typeConstructor()
|
||||
|
||||
val isTypeInferenceForSelfTypesSupported =
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.TypeInferenceOnCallsWithSelfTypes)
|
||||
if (isTypeInferenceForSelfTypesSupported && argumentTypeConstructor is TypeVariableTypeConstructorMarker && conf.selfTypesWithTypeVariablesToCapturedStarProjection) {
|
||||
// If we have Self<TypeVariable(T)> where T is bounded by Self<T>, we approximate it to CapturedType(*) to satisfy constraints
|
||||
if (argumentTypeConstructor.typeParameter?.hasRecursiveBounds(type.typeConstructor()) == true) {
|
||||
return createCapturedStarProjectionForSelfType(argumentTypeConstructor, type)
|
||||
}
|
||||
}
|
||||
|
||||
val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
||||
|
||||
val argumentType = newArguments[index]?.getType() ?: argument.getType()
|
||||
|
||||
-7
@@ -24,7 +24,6 @@ open class TypeApproximatorConfiguration {
|
||||
open val intersection: IntersectionStrategy = IntersectionStrategy.TO_COMMON_SUPERTYPE
|
||||
open val intersectionTypesInContravariantPositions = false
|
||||
open val localTypes = false
|
||||
open val selfTypesWithTypeVariablesToCapturedStarProjection = false
|
||||
|
||||
open val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean = { false }
|
||||
open fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean =
|
||||
@@ -74,12 +73,6 @@ open class TypeApproximatorConfiguration {
|
||||
override val intersectionTypesInContravariantPositions: Boolean get() = true
|
||||
}
|
||||
|
||||
object InternalAndSelfTypesApproximation : AbstractCapturedTypesApproximation(CaptureStatus.FROM_EXPRESSION) {
|
||||
override val integerLiteralType: Boolean get() = true
|
||||
override val intersectionTypesInContravariantPositions: Boolean get() = true
|
||||
override val selfTypesWithTypeVariablesToCapturedStarProjection = true
|
||||
}
|
||||
|
||||
object FinalApproximationAfterResolutionAndInference :
|
||||
AbstractCapturedTypesApproximation(CaptureStatus.FROM_EXPRESSION) {
|
||||
override val integerLiteralType: Boolean get() = true
|
||||
|
||||
+3
-9
@@ -22,10 +22,7 @@ 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,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) : TypeSystemInferenceExtensionContextDelegate,
|
||||
class ClassicTypeSystemContextForCS(override val builtIns: KotlinBuiltIns) : TypeSystemInferenceExtensionContextDelegate,
|
||||
ClassicTypeSystemContext,
|
||||
BuiltInsProvider {
|
||||
|
||||
@@ -48,16 +45,13 @@ class ClassicTypeSystemContextForCS(
|
||||
require(lowerType is UnwrappedType?, lowerType::errorMessage)
|
||||
require(constructorProjection is TypeProjectionBase, constructorProjection::errorMessage)
|
||||
|
||||
val isTypeInferenceForSelfTypesSupported =
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.TypeInferenceOnCallsWithSelfTypes)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val newCapturedTypeConstructor = NewCapturedTypeConstructor(
|
||||
constructorProjection,
|
||||
constructorSupertypes as List<UnwrappedType>
|
||||
)
|
||||
return NewCapturedType(
|
||||
if (isTypeInferenceForSelfTypesSupported) captureStatus else CaptureStatus.FOR_INCORPORATION,
|
||||
captureStatus,
|
||||
newCapturedTypeConstructor,
|
||||
lowerType = lowerType
|
||||
)
|
||||
@@ -117,5 +111,5 @@ fun NewConstraintSystemImpl(
|
||||
constraintInjector: ConstraintInjector,
|
||||
builtIns: KotlinBuiltIns
|
||||
): NewConstraintSystemImpl {
|
||||
return NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns, constraintInjector.languageVersionSettings))
|
||||
return NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns))
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
|
||||
class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns) : SimpleConstraintSystem {
|
||||
val system = NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns, constraintInjector.languageVersionSettings))
|
||||
val system = NewConstraintSystemImpl(constraintInjector, ClassicTypeSystemContextForCS(builtIns))
|
||||
val csBuilder: ConstraintSystemBuilder =
|
||||
system.getBuilder()
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextFor
|
||||
class TypeApproximator(
|
||||
builtIns: KotlinBuiltIns,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
) : AbstractTypeApproximator(ClassicTypeSystemContextForCS(builtIns, languageVersionSettings), languageVersionSettings) {
|
||||
) : AbstractTypeApproximator(ClassicTypeSystemContextForCS(builtIns), languageVersionSettings) {
|
||||
fun approximateDeclarationType(baseType: KotlinType, local: Boolean): UnwrappedType {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return baseType.unwrap()
|
||||
|
||||
|
||||
@@ -177,6 +177,16 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
||||
fun SimpleTypeMarker.replaceArguments(newArguments: List<TypeArgumentMarker>): SimpleTypeMarker
|
||||
fun SimpleTypeMarker.replaceArguments(replacement: (TypeArgumentMarker) -> TypeArgumentMarker): SimpleTypeMarker
|
||||
|
||||
fun KotlinTypeMarker.replaceArguments(replacement: (TypeArgumentMarker) -> TypeArgumentMarker) =
|
||||
when (this) {
|
||||
is SimpleTypeMarker -> replaceArguments(replacement)
|
||||
is FlexibleTypeMarker -> createFlexibleType(
|
||||
lowerBound().replaceArguments(replacement),
|
||||
upperBound().replaceArguments(replacement)
|
||||
)
|
||||
else -> error("sealed")
|
||||
}
|
||||
|
||||
fun KotlinTypeMarker.hasExactAnnotation(): Boolean
|
||||
fun KotlinTypeMarker.hasNoInferAnnotation(): Boolean
|
||||
|
||||
@@ -252,16 +262,18 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
||||
|
||||
fun createCapturedStarProjectionForSelfType(
|
||||
typeVariable: TypeVariableTypeConstructorMarker,
|
||||
selfType: SimpleTypeMarker,
|
||||
typesForRecursiveTypeParameters: List<KotlinTypeMarker>,
|
||||
): SimpleTypeMarker? {
|
||||
val typeParameter = typeVariable.typeParameter ?: return null
|
||||
val starProjection = createStarProjection(typeParameter)
|
||||
val superType = selfType.replaceArguments {
|
||||
val constructor = it.getType().typeConstructor()
|
||||
if (constructor is TypeVariableTypeConstructorMarker && constructor == typeVariable) {
|
||||
starProjection
|
||||
} else it
|
||||
}
|
||||
val superType = intersectTypes(
|
||||
typesForRecursiveTypeParameters.map { type ->
|
||||
type.replaceArguments {
|
||||
val constructor = it.getType().typeConstructor()
|
||||
if (constructor is TypeVariableTypeConstructorMarker && constructor == typeVariable) starProjection else it
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return createCapturedType(starProjection, listOf(superType), lowerType = null, CaptureStatus.FROM_EXPRESSION)
|
||||
}
|
||||
@@ -310,6 +322,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
||||
|
||||
fun KotlinTypeMarker.argumentsCount(): Int
|
||||
fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker
|
||||
fun KotlinTypeMarker.getArguments(): List<TypeArgumentMarker>
|
||||
|
||||
fun SimpleTypeMarker.getArgumentOrNull(index: Int): TypeArgumentMarker? {
|
||||
if (index in 0 until argumentsCount()) return getArgument(index)
|
||||
|
||||
@@ -180,6 +180,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
return this.arguments[index]
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.getArguments(): List<TypeArgumentMarker> {
|
||||
require(this is KotlinType, this::errorMessage)
|
||||
return this.arguments
|
||||
}
|
||||
|
||||
override fun TypeArgumentMarker.isStarProjection(): Boolean {
|
||||
require(this is TypeProjection, this::errorMessage)
|
||||
return this.isStarProjection
|
||||
|
||||
Reference in New Issue
Block a user