diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index 80c81233046..6502ab025bf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -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)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpander.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpander.kt index 48e1d48d605..dba1cf04169 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpander.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpander.kt @@ -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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpansion.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpansion.kt index a58ca27c061..1f28b291879 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpansion.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpansion.kt @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index dc9cf622874..84f09123f33 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -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, diff --git a/compiler/testData/diagnostics/tests/typealias/recursive.kt b/compiler/testData/diagnostics/tests/typealias/recursive.kt index 97ea09f10ee..485491f1dac 100644 --- a/compiler/testData/diagnostics/tests/typealias/recursive.kt +++ b/compiler/testData/diagnostics/tests/typealias/recursive.kt @@ -1,4 +1,11 @@ +typealias R = R + +typealias L = List + typealias A = B typealias B = A +typealias F1 = (Int) -> F2 +typealias F2 = (F1) -> Int + val x: A = TODO() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typealias/recursive.txt b/compiler/testData/diagnostics/tests/typealias/recursive.txt index f2d84f0bba0..61c8e999fc0 100644 --- a/compiler/testData/diagnostics/tests/typealias/recursive.txt +++ b/compiler/testData/diagnostics/tests/typealias/recursive.txt @@ -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 +public typealias R = R public val x: [ERROR : Recursive type alias: A]