Build recursive raw types and raw types which contain type parameters properly
1) Substitute erasure of other type parameters 2) Use star projection at top level for recursive raw types ^KT-46126 Fixed
This commit is contained in:
@@ -185,7 +185,74 @@ fun KotlinType.contains(predicate: (UnwrappedType) -> Boolean) = TypeUtils.conta
|
||||
fun KotlinType.replaceArgumentsWithStarProjections() = replaceArgumentsWith(::StarProjectionImpl)
|
||||
fun KotlinType.replaceArgumentsWithNothing() = replaceArgumentsWith { it.builtIns.nothingType.asTypeProjection() }
|
||||
|
||||
private inline fun KotlinType.replaceArgumentsWith(replacement: (TypeParameterDescriptor) -> TypeProjection): KotlinType {
|
||||
fun KotlinType.extractTypeParametersFromUpperBounds(upperBoundOfTypeParameter: TypeParameterDescriptor?): Set<TypeParameterDescriptor> =
|
||||
mutableSetOf<TypeParameterDescriptor>().also { extractTypeParametersFromUpperBounds(this, it, upperBoundOfTypeParameter) }
|
||||
|
||||
private fun KotlinType.extractTypeParametersFromUpperBounds(
|
||||
baseType: KotlinType,
|
||||
to: MutableSet<TypeParameterDescriptor>,
|
||||
upperBoundOfTypeParameter: TypeParameterDescriptor?
|
||||
) {
|
||||
val declarationDescriptor = constructor.declarationDescriptor
|
||||
|
||||
if (declarationDescriptor is TypeParameterDescriptor) {
|
||||
if (constructor != baseType.constructor) {
|
||||
to += declarationDescriptor
|
||||
} else {
|
||||
for (upperBound in declarationDescriptor.upperBounds) {
|
||||
upperBound.extractTypeParametersFromUpperBounds(baseType, to, upperBoundOfTypeParameter)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val typeParameters = (constructor.declarationDescriptor as? ClassifierDescriptorWithTypeParameters)?.declaredTypeParameters
|
||||
for ((i, argument) in arguments.withIndex()) {
|
||||
val typeParameter = typeParameters?.get(i)
|
||||
if (argument.isStarProjection || (typeParameter != null && typeParameter == upperBoundOfTypeParameter)) continue
|
||||
if (argument.type.constructor.declarationDescriptor in to || argument.type.constructor == baseType.constructor) continue
|
||||
argument.type.extractTypeParametersFromUpperBounds(baseType, to, upperBoundOfTypeParameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun hasTypeParameterRecursiveBounds(
|
||||
typeParameter: TypeParameterDescriptor,
|
||||
selfConstructor: TypeConstructor? = null,
|
||||
upperBoundOfTypeParameter: TypeParameterDescriptor? = null
|
||||
): Boolean =
|
||||
typeParameter.upperBounds.any { upperBound ->
|
||||
upperBound.containsSelfTypeParameter(typeParameter.defaultType.constructor, upperBoundOfTypeParameter)
|
||||
&& (selfConstructor == null || upperBound.constructor == selfConstructor)
|
||||
}
|
||||
|
||||
private fun KotlinType.containsSelfTypeParameter(
|
||||
baseConstructor: TypeConstructor,
|
||||
upperBoundOfTypeParameter: TypeParameterDescriptor?
|
||||
): Boolean {
|
||||
if (this.constructor == baseConstructor) return true
|
||||
|
||||
val typeParameters = (constructor.declarationDescriptor as? ClassifierDescriptorWithTypeParameters)?.declaredTypeParameters
|
||||
return arguments.withIndex().any { (i, argument) ->
|
||||
val typeParameter = typeParameters?.get(i)
|
||||
if ((typeParameter != null && typeParameter == upperBoundOfTypeParameter) || argument.isStarProjection) return@any false
|
||||
argument.type.containsSelfTypeParameter(baseConstructor, upperBoundOfTypeParameter)
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinType.replaceArgumentsWithStarProjectionOrMapped(
|
||||
substitutor: TypeSubstitutor,
|
||||
substitutionMap: Map<TypeConstructor, TypeProjection>,
|
||||
variance: Variance,
|
||||
upperBoundOfTypeParameter: TypeParameterDescriptor?
|
||||
) =
|
||||
replaceArgumentsWith { typeParameterDescriptor ->
|
||||
val argument = arguments.getOrNull(typeParameterDescriptor.index)
|
||||
if (typeParameterDescriptor != upperBoundOfTypeParameter && argument != null && argument.type.constructor in substitutionMap) {
|
||||
argument
|
||||
} else StarProjectionImpl(typeParameterDescriptor)
|
||||
}.let { substitutor.safeSubstitute(it, variance) }
|
||||
|
||||
|
||||
inline fun KotlinType.replaceArgumentsWith(replacement: (TypeParameterDescriptor) -> TypeProjection): KotlinType {
|
||||
val unwrapped = unwrap()
|
||||
return when (unwrapped) {
|
||||
is FlexibleType -> KotlinTypeFactory.flexibleType(
|
||||
@@ -196,7 +263,7 @@ private inline fun KotlinType.replaceArgumentsWith(replacement: (TypeParameterDe
|
||||
}.inheritEnhancement(unwrapped)
|
||||
}
|
||||
|
||||
private inline fun SimpleType.replaceArgumentsWith(replacement: (TypeParameterDescriptor) -> TypeProjection): SimpleType {
|
||||
inline fun SimpleType.replaceArgumentsWith(replacement: (TypeParameterDescriptor) -> TypeProjection): SimpleType {
|
||||
if (constructor.parameters.isEmpty() || constructor.declarationDescriptor == null) return this
|
||||
|
||||
val newArguments = constructor.parameters.map(replacement)
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.hasTypeParameterRecursiveBounds
|
||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
|
||||
@@ -220,11 +221,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
return this.typeConstructor
|
||||
}
|
||||
|
||||
override fun TypeParameterMarker.doesFormSelfType(selfConstructor: TypeConstructorMarker): Boolean {
|
||||
override fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker): Boolean {
|
||||
require(this is TypeParameterDescriptor, this::errorMessage)
|
||||
require(selfConstructor is TypeConstructor, this::errorMessage)
|
||||
|
||||
return doesTypeParameterFormSelfType(this, selfConstructor)
|
||||
return hasTypeParameterRecursiveBounds(this, selfConstructor)
|
||||
}
|
||||
|
||||
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
||||
import java.util.*
|
||||
|
||||
@@ -106,8 +105,3 @@ private fun TypeConstructor.debugInfo() = buildString {
|
||||
interface NewTypeVariableConstructor {
|
||||
val originalTypeParameter: TypeParameterDescriptor?
|
||||
}
|
||||
|
||||
fun doesTypeParameterFormSelfType(typeParameter: TypeParameterDescriptor, selfConstructor: TypeConstructor) =
|
||||
typeParameter.upperBounds.any { upperBound ->
|
||||
upperBound.contains { it.constructor == typeParameter.typeConstructor } && upperBound.constructor == selfConstructor
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user