diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt index 9cf888532d7..b442480c271 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt @@ -25,48 +25,46 @@ abstract class AbstractTypeConstructor(storageManager: StorageManager) : TypeCon // In current version diagnostic about loops in supertypes is reported on each vertex (supertype reference) that lies on the cycle. // To achieve that we store both versions of supertypes --- before and after loops disconnection. // The first one is used for computation of neighbours in supertypes graph (see Companion.computeNeighbours) - private class Supertypes( - val allSupertypes: Collection) { - // initializer is only needed as a stub for case when 'getSupertypes' is called while 'supertypes' are being calculated - var supertypesWithoutCycles: List = listOf(ErrorUtils.ERROR_TYPE_FOR_LOOP_IN_SUPERTYPES) + private class Supertypes(val allSupertypes: Collection) { + // initializer is only needed as a stub for case when 'getSupertypes' is called while 'supertypes' are being calculated + var supertypesWithoutCycles: List = listOf(ErrorUtils.ERROR_TYPE_FOR_LOOP_IN_SUPERTYPES) } private val supertypes = storageManager.createLazyValueWithPostCompute( - { Supertypes(computeSupertypes()) }, - { Supertypes(listOf(ErrorUtils.ERROR_TYPE_FOR_LOOP_IN_SUPERTYPES)) }, - { supertypes -> - // It's important that loops disconnection begins in post-compute phase, because it guarantees that - // when we start calculation supertypes of supertypes (for computing neighbours), they start their disconnection loop process - // either, and as we want to report diagnostic about loops on all declarations they should see consistent version of 'allSupertypes' - var resultWithoutCycles = - supertypeLoopChecker.findLoopsInSupertypesAndDisconnect( - this, supertypes.allSupertypes, - { it.computeNeighbours(useCompanions = false) }, - { reportSupertypeLoopError(it) } - ) - - if (resultWithoutCycles.isEmpty()) { - resultWithoutCycles = defaultSupertypeIfEmpty()?.let { listOf(it) }.orEmpty() - } - - // We also check if there are a loop with additional edges going from owner of companion to - // the companion itself. - // Note that we use already disconnected types to not report two diagnostics on cyclic supertypes + { Supertypes(computeSupertypes()) }, + { Supertypes(listOf(ErrorUtils.ERROR_TYPE_FOR_LOOP_IN_SUPERTYPES)) }, + { supertypes -> + // It's important that loops disconnection begins in post-compute phase, because it guarantees that + // when we start calculation supertypes of supertypes (for computing neighbours), they start their disconnection loop process + // either, and as we want to report diagnostic about loops on all declarations they should see consistent version of 'allSupertypes' + var resultWithoutCycles = supertypeLoopChecker.findLoopsInSupertypesAndDisconnect( - this, resultWithoutCycles, - { it.computeNeighbours(useCompanions = true) }, - { reportScopesLoopError(it) } + this, supertypes.allSupertypes, + { it.computeNeighbours(useCompanions = false) }, + { reportSupertypeLoopError(it) } ) - supertypes.supertypesWithoutCycles = (resultWithoutCycles as? List) ?: resultWithoutCycles.toList() - }) + if (resultWithoutCycles.isEmpty()) { + resultWithoutCycles = defaultSupertypeIfEmpty()?.let { listOf(it) }.orEmpty() + } + + // We also check if there are a loop with additional edges going from owner of companion to + // the companion itself. + // Note that we use already disconnected types to not report two diagnostics on cyclic supertypes + supertypeLoopChecker.findLoopsInSupertypesAndDisconnect( + this, resultWithoutCycles, + { it.computeNeighbours(useCompanions = true) }, + { reportScopesLoopError(it) } + ) + + supertypes.supertypesWithoutCycles = (resultWithoutCycles as? List) ?: resultWithoutCycles.toList() + }) private fun TypeConstructor.computeNeighbours(useCompanions: Boolean): Collection = - (this as? AbstractTypeConstructor)?.let { - abstractClassifierDescriptor -> - abstractClassifierDescriptor.supertypes().allSupertypes + - abstractClassifierDescriptor.getAdditionalNeighboursInSupertypeGraph(useCompanions) - } ?: supertypes + (this as? AbstractTypeConstructor)?.let { abstractClassifierDescriptor -> + abstractClassifierDescriptor.supertypes().allSupertypes + + abstractClassifierDescriptor.getAdditionalNeighboursInSupertypeGraph(useCompanions) + } ?: supertypes protected abstract fun computeSupertypes(): Collection protected abstract val supertypeLoopChecker: SupertypeLoopChecker