diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index 01e9189cae5..569fc7679d3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -116,13 +116,42 @@ public class TypeResolver( if (!type.isBare) { for (argument in type.actualType.arguments) { - ForceResolveUtil.forceResolveAllContents(argument.type) + forceResolveTypeContents(argument.type) } } return type } + /** + * This function is light version of ForceResolveUtil.forceResolveAllContents + * We can't use ForceResolveUtil.forceResolveAllContents here because it runs ForceResolveUtil.forceResolveAllContents(getConstructor()), + * which is unsafe for some cyclic cases. For Example: + * class A: List { + * class B + * } + * Here when we resolve class B, we should resolve supertype for A and we shouldn't start resolve for class B, + * otherwise it would be a cycle. + * Now there is no cycle here because member scope for A is very clever and can get lazy descriptor for class B without resolving it. + * + * todo: find another way after release + */ + private fun forceResolveTypeContents(type: JetType) { + type.annotations // force read type annotations + if (type.isFlexible()) { + forceResolveTypeContents(type.flexibility().lowerBound) + forceResolveTypeContents(type.flexibility().upperBound) + } + else { + type.constructor // force read type constructor + for (projection in type.arguments) { + if (!projection.isStarProjection) { + forceResolveTypeContents(projection.type) + } + } + } + } + private fun resolveTypeElement(c: TypeResolutionContext, annotations: Annotations, typeElement: JetTypeElement?): PossiblyBareType { var result: PossiblyBareType? = null typeElement?.accept(object : JetVisitorVoid() { @@ -343,7 +372,7 @@ public class TypeResolver( if (userType.qualifier != null) { // we must resolve all type references in arguments of qualifier type for (typeArgument in userType.qualifier!!.typeArguments) { typeArgument.typeReference?.let { - ForceResolveUtil.forceResolveAllContents(resolveType(scope, it, trace, true)) + forceResolveTypeContents(resolveType(scope, it, trace, true)) } } } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/nestedClassInSuperClassParameter.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/nestedClassInSuperClassParameter.kt new file mode 100644 index 00000000000..f33ddf14c37 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/nestedClassInSuperClassParameter.kt @@ -0,0 +1,5 @@ +open class X + +class A: X() { + class B +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/nestedClassInSuperClassParameter.txt b/compiler/testData/diagnostics/tests/cyclicHierarchy/nestedClassInSuperClassParameter.txt new file mode 100644 index 00000000000..fb0dd81faf2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/nestedClassInSuperClassParameter.txt @@ -0,0 +1,22 @@ +package + +public final class A : X { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public open class X { + public constructor X() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 3a1e83bc189..32974f44fa2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -3381,6 +3381,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("nestedClassInSuperClassParameter.kt") + public void testNestedClassInSuperClassParameter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy/nestedClassInSuperClassParameter.kt"); + doTest(fileName); + } + @TestMetadata("twoClassesWithNestedCycle.kt") public void testTwoClassesWithNestedCycle() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy/twoClassesWithNestedCycle.kt");