diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt index fc9fcf103e3..d898ad47225 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt @@ -7,7 +7,10 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.utils.classId import org.jetbrains.kotlin.fir.psi +import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.psi.KtElement @@ -33,6 +36,28 @@ object FirElementFinder { } } } + + override fun visitRegularClass(regularClass: FirRegularClass) { + // Checking the rest super types that weren't resolved on the first OUTER_CLASS_ARGUMENTS_REQUIRED check in FirTypeResolver + val oldResolvePhase = regularClass.resolvePhase + val oldList = regularClass.superTypeRefs.toList() + + try { + super.visitRegularClass(regularClass) + } catch (e: ConcurrentModificationException) { + val newResolvePhase = regularClass.resolvePhase + val newList = regularClass.superTypeRefs.toList() + + throw IllegalStateException( + """ + CME while traversing superTypeRefs of declaration=${regularClass.render()}: + classId: ${regularClass.classId}, + oldPhase: $oldResolvePhase, oldList: ${oldList.joinToString(",", "[", "]") { it.render() }}, + newPhase: $newResolvePhase, newList: ${newList.joinToString(",", "[", "]") { it.render() }} + """.trimIndent(), e + ) + } + } }) return result } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOuterClassArgumentsRequiredChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOuterClassArgumentsRequiredChecker.kt index 247b1228086..125f6bb1d7f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOuterClassArgumentsRequiredChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOuterClassArgumentsRequiredChecker.kt @@ -11,6 +11,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.extractArgumentsTypeRefAndSource import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.utils.classId +import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.isValidTypeParameterFromOuterDeclaration import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toTypeProjections @@ -20,8 +22,25 @@ import org.jetbrains.kotlin.fir.types.* object FirOuterClassArgumentsRequiredChecker : FirRegularClassChecker() { override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { // Checking the rest super types that weren't resolved on the first OUTER_CLASS_ARGUMENTS_REQUIRED check in FirTypeResolver - for (superTypeRef in declaration.superTypeRefs) { - checkOuterClassArgumentsRequired(superTypeRef, declaration, context, reporter) + val oldResolvePhase = declaration.resolvePhase + val oldList = declaration.superTypeRefs.toList() + + try { + for (superTypeRef in declaration.superTypeRefs) { + checkOuterClassArgumentsRequired(superTypeRef, declaration, context, reporter) + } + } catch (e: ConcurrentModificationException) { + val newResolvePhase = declaration.resolvePhase + val newList = declaration.superTypeRefs.toList() + + throw IllegalStateException( + """ + CME while traversing superTypeRefs of declaration=${declaration.render()}: + classId: ${declaration.classId}, + oldPhase: $oldResolvePhase, oldList: ${oldList.joinToString { it.render() }}, + newPhase: $newResolvePhase, newList: ${newList.joinToString { it.render() }} + """.trimIndent(), e + ) } }