From 0b34d66b87906de44cf56e0140fd0817bb2ae164 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 12 Mar 2024 11:38:34 +0100 Subject: [PATCH] Revert "FIR: Report CAPTURED_VAL_INITIALIZATION if initialization is done" This reverts commit 1c4023fda579aa17bd53810cacf43052fe826103. #KT-64854 Submitted #KT-59906 Submitted --- .../cfa/FirPropertyInitializationAnalyzer.kt | 7 --- .../cfa/util/PropertyInitializationInfo.kt | 2 - .../PropertyInitializationInfoCollector.kt | 57 ------------------- .../fieldInitialization.fir.kt | 46 ++------------- .../fieldInitialization.kt | 40 +------------ .../fieldInitialization.txt | 5 -- .../valDefiniteInitialization.fir.kt | 2 +- 7 files changed, 10 insertions(+), 149 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt index d7a748ad602..995d74f52a3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt @@ -131,13 +131,6 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses( else FirErrors.CAPTURED_VAL_INITIALIZATION reporter.reportOn(node.fir.lValue.source, error, symbol, context) - } else if (!symbol.isLocal && getValue(node).values.any { symbol !in it.initializedInsideConstructor }) { - /* If the assignment is inside INVOKE_ONCE lambda and the lambda is not inlined, - backend generates either separate function or separate class for the lambda. - If we try to initialize non-static final field there, we will get exception at - runtime, since we can initialize such fields only inside constructors. - */ - reporter.reportOn(node.fir.lValue.source, FirErrors.CAPTURED_VAL_INITIALIZATION, symbol, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfo.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfo.kt index c10c1ffc6b1..3364047052a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfo.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfo.kt @@ -47,8 +47,6 @@ class PropertyInitializationInfo( val EMPTY = PropertyInitializationInfo() } - val initializedInsideConstructor: MutableSet = mutableSetOf() - override val constructor: (PersistentMap) -> PropertyInitializationInfo = ::PropertyInitializationInfo } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfoCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfoCollector.kt index 2fb2d77a6e4..e7e96989ef0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfoCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfoCollector.kt @@ -7,8 +7,6 @@ package org.jetbrains.kotlin.fir.analysis.cfa.util import kotlinx.collections.immutable.persistentMapOf import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange -import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction -import org.jetbrains.kotlin.fir.declarations.InlineStatus import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.calleeReference import org.jetbrains.kotlin.fir.expressions.dispatchReceiver @@ -42,8 +40,6 @@ class PropertyInitializationInfoCollector( private val EMPTY_INFO: PathAwarePropertyInitializationInfo = persistentMapOf(NormalPath to PropertyInitializationInfo.EMPTY) } - private val scopeStack = arrayListOf() - override val emptyInfo: PathAwarePropertyInitializationInfo get() = EMPTY_INFO @@ -62,17 +58,6 @@ class PropertyInitializationInfoCollector( val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return dataForNode if (symbol !in localProperties) return dataForNode return addRange(dataForNode, symbol, EventOccurrencesRange.EXACTLY_ONCE) - .also { it.setPropertyAsInitializedInsideConstructorIfNeeded(symbol) } - } - - private fun PathAwarePropertyInitializationInfo.setPropertyAsInitializedInsideConstructorIfNeeded( - symbol: FirPropertySymbol, - ) { - if (scopeStack.all { (it.declaration as? FirAnonymousFunction)?.inlineStatus == InlineStatus.Inline }) { - for (info in values) { - info.initializedInsideConstructor.add(symbol) - } - } } override fun visitVariableDeclarationNode( @@ -137,48 +122,6 @@ class PropertyInitializationInfoCollector( declaredVariableCollector.exitCapturingStatement(node.fir) return visitNode(node, data) } - - override fun visitFunctionEnterNode( - node: FunctionEnterNode, - data: PathAwareControlFlowInfo - ): PathAwareControlFlowInfo { - if (node.owner.declaration is FirAnonymousFunction) { - scopeStack.add(node.owner) - } - return super.visitFunctionEnterNode(node, data) - } - - override fun visitFunctionExitNode( - node: FunctionExitNode, - data: PathAwareControlFlowInfo - ): PathAwareControlFlowInfo { - if (node.owner.declaration is FirAnonymousFunction) { - assert(scopeStack.isNotEmpty() && node.owner == scopeStack.last()) { - "Unexpected scopeStack's top. Expected: ${node.owner.name}, but got: ${if (scopeStack.isEmpty()) "null" else scopeStack.last().name}" - } - scopeStack.removeLast() - } - return super.visitFunctionExitNode(node, data) - } - - override fun visitAnonymousObjectEnterNode( - node: AnonymousObjectEnterNode, - data: PathAwareControlFlowInfo - ): PathAwareControlFlowInfo { - scopeStack.add(node.owner) - return super.visitAnonymousObjectEnterNode(node, data) - } - - override fun visitAnonymousObjectExpressionExitNode( - node: AnonymousObjectExpressionExitNode, - data: PathAwareControlFlowInfo - ): PathAwareControlFlowInfo { - assert(scopeStack.isNotEmpty() && node.owner == scopeStack.last()) { - "Unexpected scopeStack's top. Expected: ${node.owner.name}, but got: ${if (scopeStack.isEmpty()) "null" else scopeStack.last().name}" - } - scopeStack.removeLast() - return super.visitAnonymousObjectExpressionExitNode(node, data) - } } internal fun , K : Any> addRange( diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.fir.kt index 11762189c12..2efb4954808 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.fir.kt @@ -42,53 +42,19 @@ class Test { val b: String val c: String val d: String - val e: String - val f: String - val g: String - val h: String - val i: String init { inlineMe { a = "allowed" } crossinlineMe { - b = "not allowed" + b = "not allowed" } noinlineMe { - c = "not allowed" + c = "not allowed" } notinline { - d = "not allowed" - } - - crossinlineMe { - inlineMe { - e = "not allowed" - } - } - - fun localFun() { - f = "not allowed" - } - - val localLambda = { - g = "not allowed" - } - - object { - val o: String - - init { - h = "not allowed" - o = "allowed" - } - } - - class Local { - init { - i = "not allowed" - } + d = "not allowed" } } } @@ -175,12 +141,12 @@ class Test5 { a = "OK" } val bInit = crossinlineMe { - b = "not allowed" + b = "OK" } val cInit = noinlineMe { - c = "not allowed" + c = "OK" } val dInit = notinline { - d = "not allowed" + d = "OK" } } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.kt index 040748c8210..9038dcaa5ba 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.kt @@ -42,11 +42,6 @@ class Test { val b: String val c: String val d: String - val e: String - val f: String - val g: String - val h: String - val i: String init { inlineMe { @@ -61,35 +56,6 @@ class Test { notinline { d = "not allowed" } - - crossinlineMe { - inlineMe { - e = "not allowed" - } - } - - fun localFun() { - f = "not allowed" - } - - val localLambda = { - g = "not allowed" - } - - object { - val o: String - - init { - h = "not allowed" - o = "allowed" - } - } - - class Local { - init { - i = "not allowed" - } - } } } @@ -175,12 +141,12 @@ class Test5 { a = "OK" } val bInit = crossinlineMe { - b = "not allowed" + b = "OK" } val cInit = noinlineMe { - c = "not allowed" + c = "OK" } val dInit = notinline { - d = "not allowed" + d = "OK" } } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.txt index 94ebc65dc81..012c3fbc21e 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.txt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldInitialization.txt @@ -18,11 +18,6 @@ package public final val b: kotlin.String public final val c: kotlin.String public final val d: kotlin.String - public final val e: kotlin.String - public final val f: kotlin.String - public final val g: kotlin.String - public final val h: kotlin.String - public final val i: kotlin.String public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.fir.kt index 5736a9d69d6..79b8359396e 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.fir.kt @@ -86,7 +86,7 @@ class DefiniteInitializationInInitSection { val y: Int init { - myRun { x = 42 } + myRun { x = 42 } unknownRun { y = 239 } } }