Revert "FIR: Report CAPTURED_VAL_INITIALIZATION if initialization is done"
This reverts commit 1c4023fda5.
#KT-64854 Submitted
#KT-59906 Submitted
This commit is contained in:
committed by
Space Team
parent
0fe793943d
commit
0b34d66b87
-7
@@ -131,13 +131,6 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses(
|
|||||||
else
|
else
|
||||||
FirErrors.CAPTURED_VAL_INITIALIZATION
|
FirErrors.CAPTURED_VAL_INITIALIZATION
|
||||||
reporter.reportOn(node.fir.lValue.source, error, symbol, context)
|
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-2
@@ -47,8 +47,6 @@ class PropertyInitializationInfo(
|
|||||||
val EMPTY = PropertyInitializationInfo()
|
val EMPTY = PropertyInitializationInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
val initializedInsideConstructor: MutableSet<FirPropertySymbol> = mutableSetOf()
|
|
||||||
|
|
||||||
override val constructor: (PersistentMap<FirPropertySymbol, EventOccurrencesRange>) -> PropertyInitializationInfo =
|
override val constructor: (PersistentMap<FirPropertySymbol, EventOccurrencesRange>) -> PropertyInitializationInfo =
|
||||||
::PropertyInitializationInfo
|
::PropertyInitializationInfo
|
||||||
}
|
}
|
||||||
|
|||||||
-57
@@ -7,8 +7,6 @@ package org.jetbrains.kotlin.fir.analysis.cfa.util
|
|||||||
|
|
||||||
import kotlinx.collections.immutable.persistentMapOf
|
import kotlinx.collections.immutable.persistentMapOf
|
||||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
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.FirThisReceiverExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.calleeReference
|
import org.jetbrains.kotlin.fir.expressions.calleeReference
|
||||||
import org.jetbrains.kotlin.fir.expressions.dispatchReceiver
|
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 EMPTY_INFO: PathAwarePropertyInitializationInfo = persistentMapOf(NormalPath to PropertyInitializationInfo.EMPTY)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val scopeStack = arrayListOf<ControlFlowGraph>()
|
|
||||||
|
|
||||||
override val emptyInfo: PathAwarePropertyInitializationInfo
|
override val emptyInfo: PathAwarePropertyInitializationInfo
|
||||||
get() = EMPTY_INFO
|
get() = EMPTY_INFO
|
||||||
|
|
||||||
@@ -62,17 +58,6 @@ class PropertyInitializationInfoCollector(
|
|||||||
val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return dataForNode
|
val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return dataForNode
|
||||||
if (symbol !in localProperties) return dataForNode
|
if (symbol !in localProperties) return dataForNode
|
||||||
return addRange(dataForNode, symbol, EventOccurrencesRange.EXACTLY_ONCE)
|
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(
|
override fun visitVariableDeclarationNode(
|
||||||
@@ -137,48 +122,6 @@ class PropertyInitializationInfoCollector(
|
|||||||
declaredVariableCollector.exitCapturingStatement(node.fir)
|
declaredVariableCollector.exitCapturingStatement(node.fir)
|
||||||
return visitNode(node, data)
|
return visitNode(node, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionEnterNode(
|
|
||||||
node: FunctionEnterNode,
|
|
||||||
data: PathAwareControlFlowInfo<PropertyInitializationInfo>
|
|
||||||
): PathAwareControlFlowInfo<PropertyInitializationInfo> {
|
|
||||||
if (node.owner.declaration is FirAnonymousFunction) {
|
|
||||||
scopeStack.add(node.owner)
|
|
||||||
}
|
|
||||||
return super.visitFunctionEnterNode(node, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitFunctionExitNode(
|
|
||||||
node: FunctionExitNode,
|
|
||||||
data: PathAwareControlFlowInfo<PropertyInitializationInfo>
|
|
||||||
): PathAwareControlFlowInfo<PropertyInitializationInfo> {
|
|
||||||
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<PropertyInitializationInfo>
|
|
||||||
): PathAwareControlFlowInfo<PropertyInitializationInfo> {
|
|
||||||
scopeStack.add(node.owner)
|
|
||||||
return super.visitAnonymousObjectEnterNode(node, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitAnonymousObjectExpressionExitNode(
|
|
||||||
node: AnonymousObjectExpressionExitNode,
|
|
||||||
data: PathAwareControlFlowInfo<PropertyInitializationInfo>
|
|
||||||
): PathAwareControlFlowInfo<PropertyInitializationInfo> {
|
|
||||||
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 <S : ControlFlowInfo<S, K, EventOccurrencesRange>, K : Any> addRange(
|
internal fun <S : ControlFlowInfo<S, K, EventOccurrencesRange>, K : Any> addRange(
|
||||||
|
|||||||
+6
-40
@@ -42,53 +42,19 @@ class Test {
|
|||||||
val b: String
|
val b: String
|
||||||
val c: String
|
val c: String
|
||||||
val d: String
|
val d: String
|
||||||
val e: String
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val f: String<!>
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val g: String<!>
|
|
||||||
val h: String
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val i: String<!>
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
inlineMe {
|
inlineMe {
|
||||||
a = "allowed"
|
a = "allowed"
|
||||||
}
|
}
|
||||||
crossinlineMe {
|
crossinlineMe {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>b<!> = "not allowed"
|
b = "not allowed"
|
||||||
}
|
}
|
||||||
noinlineMe {
|
noinlineMe {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>c<!> = "not allowed"
|
c = "not allowed"
|
||||||
}
|
}
|
||||||
notinline {
|
notinline {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>d<!> = "not allowed"
|
d = "not allowed"
|
||||||
}
|
|
||||||
|
|
||||||
crossinlineMe {
|
|
||||||
inlineMe {
|
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>e<!> = "not allowed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun localFun() {
|
|
||||||
<!CAPTURED_MEMBER_VAL_INITIALIZATION!>f<!> = "not allowed"
|
|
||||||
}
|
|
||||||
|
|
||||||
val localLambda = {
|
|
||||||
<!CAPTURED_MEMBER_VAL_INITIALIZATION!>g<!> = "not allowed"
|
|
||||||
}
|
|
||||||
|
|
||||||
object {
|
|
||||||
val o: String
|
|
||||||
|
|
||||||
init {
|
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>h<!> = "not allowed"
|
|
||||||
o = "allowed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Local {
|
|
||||||
init {
|
|
||||||
<!CAPTURED_MEMBER_VAL_INITIALIZATION!>i<!> = "not allowed"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,12 +141,12 @@ class Test5 {
|
|||||||
a = "OK"
|
a = "OK"
|
||||||
}
|
}
|
||||||
val bInit = crossinlineMe {
|
val bInit = crossinlineMe {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>b<!> = "not allowed"
|
b = "OK"
|
||||||
}
|
}
|
||||||
val cInit = noinlineMe {
|
val cInit = noinlineMe {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>c<!> = "not allowed"
|
c = "OK"
|
||||||
}
|
}
|
||||||
val dInit = notinline {
|
val dInit = notinline {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>d<!> = "not allowed"
|
d = "OK"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-37
@@ -42,11 +42,6 @@ class Test {
|
|||||||
val b: String
|
val b: String
|
||||||
val c: String
|
val c: String
|
||||||
val d: String
|
val d: String
|
||||||
val e: String
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val f: String<!>
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val g: String<!>
|
|
||||||
val h: String
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val i: String<!>
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
inlineMe {
|
inlineMe {
|
||||||
@@ -61,35 +56,6 @@ class Test {
|
|||||||
notinline {
|
notinline {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>d<!> = "not allowed"
|
<!CAPTURED_VAL_INITIALIZATION!>d<!> = "not allowed"
|
||||||
}
|
}
|
||||||
|
|
||||||
crossinlineMe {
|
|
||||||
inlineMe {
|
|
||||||
e = "not allowed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun localFun() {
|
|
||||||
<!CAPTURED_MEMBER_VAL_INITIALIZATION!>f<!> = "not allowed"
|
|
||||||
}
|
|
||||||
|
|
||||||
val <!UNUSED_VARIABLE!>localLambda<!> = {
|
|
||||||
<!CAPTURED_MEMBER_VAL_INITIALIZATION!>g<!> = "not allowed"
|
|
||||||
}
|
|
||||||
|
|
||||||
object {
|
|
||||||
val o: String
|
|
||||||
|
|
||||||
init {
|
|
||||||
h = "not allowed"
|
|
||||||
o = "allowed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Local {
|
|
||||||
init {
|
|
||||||
<!CAPTURED_MEMBER_VAL_INITIALIZATION!>i<!> = "not allowed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,12 +141,12 @@ class Test5 {
|
|||||||
a = "OK"
|
a = "OK"
|
||||||
}
|
}
|
||||||
val bInit = crossinlineMe {
|
val bInit = crossinlineMe {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>b<!> = "not allowed"
|
<!CAPTURED_VAL_INITIALIZATION!>b<!> = "OK"
|
||||||
}
|
}
|
||||||
val cInit = noinlineMe {
|
val cInit = noinlineMe {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>c<!> = "not allowed"
|
<!CAPTURED_VAL_INITIALIZATION!>c<!> = "OK"
|
||||||
}
|
}
|
||||||
val dInit = notinline {
|
val dInit = notinline {
|
||||||
<!CAPTURED_VAL_INITIALIZATION!>d<!> = "not allowed"
|
<!CAPTURED_VAL_INITIALIZATION!>d<!> = "OK"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-5
@@ -18,11 +18,6 @@ package
|
|||||||
public final val b: kotlin.String
|
public final val b: kotlin.String
|
||||||
public final val c: kotlin.String
|
public final val c: kotlin.String
|
||||||
public final val d: 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|||||||
+1
-1
@@ -86,7 +86,7 @@ class DefiniteInitializationInInitSection {
|
|||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val y: Int<!>
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val y: Int<!>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
myRun { <!CAPTURED_VAL_INITIALIZATION!>x<!> = 42 }
|
myRun { x = 42 }
|
||||||
unknownRun { <!CAPTURED_MEMBER_VAL_INITIALIZATION!>y<!> = 239 }
|
unknownRun { <!CAPTURED_MEMBER_VAL_INITIALIZATION!>y<!> = 239 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user