Recursive type alias expansion:
when resolving abbreviated type, do not check bounds if the resulting type contains type aliases.
This commit is contained in:
@@ -191,7 +191,7 @@ class DeclarationsChecker(
|
||||
|
||||
override fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor) {
|
||||
// TODO more precise diagnostics
|
||||
if (!argument.dependsOnTypeAliasParameters() && !bound.dependsOnTypeAliasParameters()) {
|
||||
if (!argument.containsTypeAliasParameters() && !bound.containsTypeAliasParameters()) {
|
||||
trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(typeReference, bound, argument, typeParameter))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ class TypeAliasExpander(
|
||||
val typeSubstitutor = TypeSubstitutor.create(substitutedType)
|
||||
|
||||
substitutedType.arguments.forEachIndexed { i, substitutedArgument ->
|
||||
if (!substitutedArgument.type.dependsOnTypeAliasParameters()) {
|
||||
if (!substitutedArgument.type.containsTypeAliasParameters()) {
|
||||
val unsubstitutedArgument = unsubstitutedType.arguments[i]
|
||||
val typeParameter = unsubstitutedType.constructor.parameters[i]
|
||||
DescriptorResolver.checkBoundsInTypeAlias(reportStrategy, unsubstitutedArgument.type, substitutedArgument.type, typeParameter, typeSubstitutor)
|
||||
|
||||
@@ -57,11 +57,16 @@ class TypeAliasExpansion private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinType.dependsOnTypeAliasParameters(): Boolean =
|
||||
fun KotlinType.containsTypeAliasParameters(): Boolean =
|
||||
TypeUtils.contains(this) {
|
||||
it.constructor.declarationDescriptor?.isTypeAliasParameter() ?: false
|
||||
}
|
||||
|
||||
fun KotlinType.containsTypeAliases(): Boolean =
|
||||
TypeUtils.contains(this) {
|
||||
it.constructor.declarationDescriptor is TypeAliasDescriptor
|
||||
}
|
||||
|
||||
fun ClassifierDescriptor.isTypeAliasParameter(): Boolean =
|
||||
this is TypeParameterDescriptor && containingDeclaration is TypeAliasDescriptor
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.Variance.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isArrayOfNothing
|
||||
|
||||
class TypeResolver(
|
||||
@@ -402,7 +403,7 @@ class TypeResolver(
|
||||
// This is not intended to be used in normal users' environments, only for tests and debugger etc
|
||||
typeTransformerForTests.transformType(resultingType)?.let { return type(it) }
|
||||
|
||||
if (c.checkBounds && !resultingType.dependsOnTypeAliasParameters()) {
|
||||
if (shouldCheckBounds(c, resultingType)) {
|
||||
val substitutor = TypeSubstitutor.create(resultingType)
|
||||
for (i in parameters.indices) {
|
||||
val parameter = parameters[i]
|
||||
@@ -423,6 +424,14 @@ class TypeResolver(
|
||||
return type(resultingType)
|
||||
}
|
||||
|
||||
private fun shouldCheckBounds(c: TypeResolutionContext, inType: KotlinType): Boolean {
|
||||
if (!c.checkBounds) return false
|
||||
if (inType.containsTypeAliasParameters()) return false
|
||||
if (c.abbreviated && inType.containsTypeAliases()) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun resolveTypeForTypeAlias(
|
||||
c: TypeResolutionContext,
|
||||
annotations: Annotations,
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
typealias R = <!RECURSIVE_TYPEALIAS_EXPANSION!>R<!>
|
||||
|
||||
typealias L = <!RECURSIVE_TYPEALIAS_EXPANSION!>List<L><!>
|
||||
|
||||
typealias A = <!RECURSIVE_TYPEALIAS_EXPANSION!>B<!>
|
||||
typealias B = <!RECURSIVE_TYPEALIAS_EXPANSION!>A<!>
|
||||
|
||||
typealias F1 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(Int) -> F2<!>
|
||||
typealias F2 = <!RECURSIVE_TYPEALIAS_EXPANSION!>(F1) -> Int<!>
|
||||
|
||||
val x: <!RECURSIVE_TYPEALIAS_EXPANSION!>A<!> = TODO()
|
||||
@@ -2,4 +2,8 @@ package
|
||||
|
||||
public typealias A = B
|
||||
public typealias B = A
|
||||
public typealias F1 = (kotlin.Int) -> F2
|
||||
public typealias F2 = (F1) -> kotlin.Int
|
||||
public typealias L = kotlin.collections.List<L>
|
||||
public typealias R = R
|
||||
public val x: [ERROR : Recursive type alias: A]
|
||||
|
||||
Reference in New Issue
Block a user