diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/fir/caches/ValueWithPostCompute.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/fir/caches/ValueWithPostCompute.kt index 2b988334853..0fde98dbde1 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/fir/caches/ValueWithPostCompute.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/fir/caches/ValueWithPostCompute.kt @@ -36,6 +36,19 @@ internal class ValueWithPostCompute( @Volatile private var value: Any? = ValueIsNotComputed + private val guard = ThreadLocal.withInitial { false } + private inline fun recursiveGuarded(body: () -> T): T { + check(!guard.get()) { + "Should not be called recursively" + } + guard.set(true) + return try { + body() + } finally { + guard.set(false) + } + } + @Suppress("UNCHECKED_CAST") fun getValue(): VALUE { when (val stateSnapshot = value) { @@ -56,7 +69,9 @@ internal class ValueWithPostCompute( return value as VALUE } val calculatedValue = try { - val (calculated, data) = _calculate!!(key) + val (calculated, data) = recursiveGuarded { + _calculate!!(key) + } value = ValueIsPostComputingNow(calculated, Thread.currentThread().id) // only current thread may see the value _postCompute!!(key, calculated, data) calculated