Use upper bound checker for typealias expansion
This commit is contained in:
@@ -250,12 +250,11 @@ class TypeAliasExpander(
|
||||
val unsubstitutedArgument = unsubstitutedType.arguments[i]
|
||||
val typeParameter = unsubstitutedType.constructor.parameters[i]
|
||||
if (shouldCheckBounds) {
|
||||
checkBoundsInTypeAlias(
|
||||
reportStrategy,
|
||||
reportStrategy.boundsViolationInSubstitution(
|
||||
typeSubstitutor,
|
||||
unsubstitutedArgument.type,
|
||||
substitutedArgument.type,
|
||||
typeParameter,
|
||||
typeSubstitutor
|
||||
typeParameter
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -265,26 +264,6 @@ class TypeAliasExpander(
|
||||
companion object {
|
||||
private const val MAX_RECURSION_DEPTH = 100
|
||||
|
||||
fun checkBoundsInTypeAlias(
|
||||
reportStrategy: TypeAliasExpansionReportStrategy,
|
||||
unsubstitutedArgument: KotlinType,
|
||||
typeArgument: KotlinType,
|
||||
typeParameterDescriptor: TypeParameterDescriptor,
|
||||
substitutor: TypeSubstitutor
|
||||
) {
|
||||
for (bound in typeParameterDescriptor.upperBounds) {
|
||||
val substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT)
|
||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(typeArgument, substitutedBound)) {
|
||||
reportStrategy.boundsViolationInSubstitution(
|
||||
substitutedBound,
|
||||
unsubstitutedArgument,
|
||||
typeArgument,
|
||||
typeParameterDescriptor
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertRecursionDepth(recursionDepth: Int, typeAliasDescriptor: TypeAliasDescriptor) {
|
||||
if (recursionDepth > MAX_RECURSION_DEPTH) {
|
||||
throw AssertionError("Too deep recursion while expanding type alias ${typeAliasDescriptor.name}")
|
||||
|
||||
@@ -14,7 +14,7 @@ interface TypeAliasExpansionReportStrategy {
|
||||
fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, substitutedArgument: KotlinType)
|
||||
fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor)
|
||||
fun boundsViolationInSubstitution(
|
||||
bound: KotlinType,
|
||||
substitutor: TypeSubstitutor,
|
||||
unsubstitutedArgument: KotlinType,
|
||||
argument: KotlinType,
|
||||
typeParameter: TypeParameterDescriptor
|
||||
@@ -33,7 +33,7 @@ interface TypeAliasExpansionReportStrategy {
|
||||
|
||||
override fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor) {}
|
||||
override fun boundsViolationInSubstitution(
|
||||
bound: KotlinType,
|
||||
substitutor: TypeSubstitutor,
|
||||
unsubstitutedArgument: KotlinType,
|
||||
argument: KotlinType,
|
||||
typeParameter: TypeParameterDescriptor
|
||||
|
||||
@@ -88,6 +88,40 @@ fun KotlinType.getEnhancement(): KotlinType? = when (this) {
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun List<TypeProjection>.enhanceTypeArguments(depth: Int) =
|
||||
map { argument ->
|
||||
// TODO: think about star projections with enhancement (e.g. came from Java: Foo<@NotNull ?>)
|
||||
if (argument.isStarProjection) {
|
||||
return@map argument
|
||||
}
|
||||
val argumentType = argument.type
|
||||
val enhancedArgumentType = if (argumentType is TypeWithEnhancement) argumentType.enhancement else argumentType
|
||||
val enhancedDeeplyArgumentType = enhancedArgumentType.getEnhancementDeeply(depth + 1)
|
||||
|
||||
argument.replaceType(enhancedDeeplyArgumentType)
|
||||
}
|
||||
|
||||
private fun KotlinType.getEnhancementDeeply(depth: Int): KotlinType {
|
||||
val newArguments = arguments.enhanceTypeArguments(depth)
|
||||
val newArgumentsForUpperBound = if (this is FlexibleType) upperBound.arguments.enhanceTypeArguments(depth) else newArguments
|
||||
val enhancedType = if (this is TypeWithEnhancement) enhancement else this
|
||||
|
||||
return enhancedType.replace(
|
||||
newArguments = newArguments,
|
||||
newArgumentsForUpperBound = newArgumentsForUpperBound
|
||||
)
|
||||
}
|
||||
|
||||
fun KotlinType.getEnhancementDeeply(): KotlinType? {
|
||||
val enhancedTypeWithArguments = getEnhancementDeeply(depth = 0)
|
||||
|
||||
if (enhancedTypeWithArguments === this) return null
|
||||
|
||||
return enhancedTypeWithArguments
|
||||
}
|
||||
|
||||
fun KotlinType.unwrapEnhancementDeeply() = getEnhancementDeeply() ?: this
|
||||
|
||||
fun KotlinType.unwrapEnhancement(): KotlinType = getEnhancement() ?: this
|
||||
|
||||
fun UnwrappedType.inheritEnhancement(origin: KotlinType): UnwrappedType = wrapEnhancement(origin.getEnhancement())
|
||||
|
||||
Reference in New Issue
Block a user