[LL FIR] add ability to suppress contract violation exception

^KT-56543
This commit is contained in:
Dmitrii Gridin
2023-04-06 11:04:32 +02:00
committed by Space Team
parent 8387ea8a39
commit 2463b904f7
3 changed files with 29 additions and 15 deletions
@@ -5,7 +5,9 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.symbols.FirLazyResolveContractViolationException
internal class LLFirLazyResolveContractChecker { internal class LLFirLazyResolveContractChecker {
private val currentTransformerPhase = ThreadLocal.withInitial<FirResolvePhase?> { null } private val currentTransformerPhase = ThreadLocal.withInitial<FirResolvePhase?> { null }
@@ -26,12 +28,16 @@ internal class LLFirLazyResolveContractChecker {
val currentPhase = currentTransformerPhase.get() ?: return val currentPhase = currentTransformerPhase.get() ?: return
if (requestedPhase >= currentPhase) { if (requestedPhase >= currentPhase) {
error( val exception = FirLazyResolveContractViolationException(currentPhase = currentPhase, requestedPhase = requestedPhase)
"""`lazyResolveToPhase($requestedPhase)` cannot be called from a transformer with a phase $currentPhase. if (System.getProperty("kotlin.suppress.lazy.resolve.contract.violation") != null) {
`lazyResolveToPhase` can be called only from a transformer with a phase which is strictly greater than a requested phase; LoggerHolder.LOG.warn(exception)
i.e., `lazyResolveToPhase(A)` may be only called from a lazy transformer with a phase B, where A < B. This is a contract of lazy resolve""".trimIndent() } else {
) throw exception
}
} }
} }
}
private object LoggerHolder {
val LOG = Logger.getInstance(LLFirLazyResolveContractChecker::class.java)
}
}
@@ -44,6 +44,17 @@ abstract class FirLazyDeclarationResolver : FirSessionComponent {
abstract fun lazyResolveToPhaseWithCallableMembers(symbol: FirClassSymbol<*>, toPhase: FirResolvePhase) abstract fun lazyResolveToPhaseWithCallableMembers(symbol: FirClassSymbol<*>, toPhase: FirResolvePhase)
} }
class FirLazyResolveContractViolationException(
currentPhase: FirResolvePhase,
requestedPhase: FirResolvePhase,
) : IllegalStateException(
"""
`lazyResolveToPhase($requestedPhase)` cannot be called from a transformer with a phase $currentPhase.
`lazyResolveToPhase` can be called only from a transformer with a phase which is strictly greater than a requested phase;
i.e., `lazyResolveToPhase(A)` may be only called from a lazy transformer with a phase B, where A < B. This is a contract of lazy resolve
""".trimIndent()
)
val FirSession.lazyDeclarationResolver: FirLazyDeclarationResolver by FirSession.sessionComponentAccessor() val FirSession.lazyDeclarationResolver: FirLazyDeclarationResolver by FirSession.sessionComponentAccessor()
private val FirDeclaration.lazyDeclarationResolver get() = moduleData.session.lazyDeclarationResolver private val FirDeclaration.lazyDeclarationResolver get() = moduleData.session.lazyDeclarationResolver
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.test.frontend.fir.handlers
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
import org.jetbrains.kotlin.fir.symbols.FirLazyResolveContractViolationException
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
@@ -20,11 +21,11 @@ class FirCompilerLazyDeclarationResolverWithPhaseChecking : FirLazyDeclarationRe
exceptions exceptions
override fun lazyResolveToPhase(symbol: FirBasedSymbol<*>, toPhase: FirResolvePhase) { override fun lazyResolveToPhase(symbol: FirBasedSymbol<*>, toPhase: FirResolvePhase) {
checkIfCanLazyResolveToPhase(symbol, toPhase) checkIfCanLazyResolveToPhase(toPhase)
} }
override fun lazyResolveToPhaseWithCallableMembers(symbol: FirClassSymbol<*>, toPhase: FirResolvePhase) { override fun lazyResolveToPhaseWithCallableMembers(symbol: FirClassSymbol<*>, toPhase: FirResolvePhase) {
checkIfCanLazyResolveToPhase(symbol, toPhase) checkIfCanLazyResolveToPhase(toPhase)
} }
override fun startResolvingPhase(phase: FirResolvePhase) { override fun startResolvingPhase(phase: FirResolvePhase) {
@@ -37,7 +38,7 @@ class FirCompilerLazyDeclarationResolverWithPhaseChecking : FirLazyDeclarationRe
currentTransformerPhase = null currentTransformerPhase = null
} }
private fun checkIfCanLazyResolveToPhase(symbol: FirBasedSymbol<*>, requestedPhase: FirResolvePhase) { private fun checkIfCanLazyResolveToPhase(requestedPhase: FirResolvePhase) {
if (!lazyResolveContractChecksEnabled) return if (!lazyResolveContractChecksEnabled) return
val currentPhase = currentTransformerPhase val currentPhase = currentTransformerPhase
@@ -50,13 +51,9 @@ class FirCompilerLazyDeclarationResolverWithPhaseChecking : FirLazyDeclarationRe
// but due to usage of already resolved stdlib classes we don't see it // but due to usage of already resolved stdlib classes we don't see it
if (requestedPhase >= currentPhase) { if (requestedPhase >= currentPhase) {
exceptions += FirLazyResolveContractViolationException( exceptions += FirLazyResolveContractViolationException(
"""`lazyResolveToPhase($requestedPhase)` cannot be called from a transformer with a phase $currentPhase. currentPhase = currentPhase,
lazyResolveToPhase was called on a $symbol. requestedPhase = requestedPhase,
`lazyResolveToPhase` can be called only from a transformer with a phase which is strictly greater than a requested phase;
i.e., `lazyResolveToPhase(A)` may be only called from a lazy transformer with a phase B, where A < B. This is a contract of lazy resolve""".trimIndent()
) )
} }
} }
} }
class FirLazyResolveContractViolationException(message: String) : IllegalStateException(message)