diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/sortUtils.kt b/compiler/util/src/org/jetbrains/kotlin/utils/sortUtils.kt index 0784cbcceee..02e6ba6fafe 100644 --- a/compiler/util/src/org/jetbrains/kotlin/utils/sortUtils.kt +++ b/compiler/util/src/org/jetbrains/kotlin/utils/sortUtils.kt @@ -16,13 +16,17 @@ package org.jetbrains.kotlin.utils * first in the list of dependencies of `C`. Without a way to find the incoming edge from `B` to `A` while processing `C -> A`, a naive * implementation of Kahn's algorithm might order `A` before `B`. */ -fun topologicalSort(nodes: Iterable, dependencies: A.() -> Iterable): List { +fun topologicalSort( + nodes: Iterable, + reportCycle: (A) -> Nothing = { throw IllegalStateException("Cannot compute a topological sort: The node $it is in a cycle.") }, + dependencies: A.() -> Iterable, +): List { val visiting = mutableSetOf() val visited = mutableSetOf() fun visit(node: A) { if (node in visited) return - if (node in visiting) throw IllegalStateException("Cannot compute a topological sort: The node $node is in a cycle.") + if (node in visiting) reportCycle(node) // Keeping track of the nodes that are being visited allows the algorithm to throw an exception in case of a cycle. The input should // never be cyclic, but this approach gives some additional safety in case of bugs.