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