[FIR] Run CFA for member properties even if they have initializer

^KT-56678 Fixed
^KT-56682 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-02-15 12:31:26 +02:00
committed by Space Team
parent de84cb8038
commit c87e489dc9
28 changed files with 306 additions and 59 deletions
@@ -5696,6 +5696,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt"); runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt");
} }
@Test
@TestMetadata("delegatedMemberProperyWriteInInit.kt")
public void testDelegatedMemberProperyWriteInInit() throws Exception {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/delegatedMemberProperyWriteInInit.kt");
}
@Test @Test
@TestMetadata("delegatedPropertyEarlyAccess.kt") @TestMetadata("delegatedPropertyEarlyAccess.kt")
public void testDelegatedPropertyEarlyAccess() throws Exception { public void testDelegatedPropertyEarlyAccess() throws Exception {
@@ -6116,6 +6122,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt"); runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt");
} }
@Test
@TestMetadata("uninintializedProperyWithDirectAndDelayedInitialization.kt")
public void testUninintializedProperyWithDirectAndDelayedInitialization() throws Exception {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/uninintializedProperyWithDirectAndDelayedInitialization.kt");
}
@Test @Test
@TestMetadata("uninitializedCompanionOfEnum_after.kt") @TestMetadata("uninitializedCompanionOfEnum_after.kt")
public void testUninitializedCompanionOfEnum_after() throws Exception { public void testUninitializedCompanionOfEnum_after() throws Exception {
@@ -5702,6 +5702,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt"); runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt");
} }
@Test
@TestMetadata("delegatedMemberProperyWriteInInit.kt")
public void testDelegatedMemberProperyWriteInInit() throws Exception {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/delegatedMemberProperyWriteInInit.kt");
}
@Test @Test
@TestMetadata("delegatedPropertyEarlyAccess.kt") @TestMetadata("delegatedPropertyEarlyAccess.kt")
public void testDelegatedPropertyEarlyAccess() throws Exception { public void testDelegatedPropertyEarlyAccess() throws Exception {
@@ -6122,6 +6128,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt"); runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt");
} }
@Test
@TestMetadata("uninintializedProperyWithDirectAndDelayedInitialization.kt")
public void testUninintializedProperyWithDirectAndDelayedInitialization() throws Exception {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/uninintializedProperyWithDirectAndDelayedInitialization.kt");
}
@Test @Test
@TestMetadata("uninitializedCompanionOfEnum_after.kt") @TestMetadata("uninitializedCompanionOfEnum_after.kt")
public void testUninitializedCompanionOfEnum_after() throws Exception { public void testUninitializedCompanionOfEnum_after() throws Exception {
@@ -5696,6 +5696,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt"); runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt");
} }
@Test
@TestMetadata("delegatedMemberProperyWriteInInit.kt")
public void testDelegatedMemberProperyWriteInInit() throws Exception {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/delegatedMemberProperyWriteInInit.kt");
}
@Test @Test
@TestMetadata("delegatedPropertyEarlyAccess.kt") @TestMetadata("delegatedPropertyEarlyAccess.kt")
public void testDelegatedPropertyEarlyAccess() throws Exception { public void testDelegatedPropertyEarlyAccess() throws Exception {
@@ -6116,6 +6122,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt"); runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt");
} }
@Test
@TestMetadata("uninintializedProperyWithDirectAndDelayedInitialization.kt")
public void testUninintializedProperyWithDirectAndDelayedInitialization() throws Exception {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/uninintializedProperyWithDirectAndDelayedInitialization.kt");
}
@Test @Test
@TestMetadata("uninitializedCompanionOfEnum_after.kt") @TestMetadata("uninitializedCompanionOfEnum_after.kt")
public void testUninitializedCompanionOfEnum_after() throws Exception { public void testUninitializedCompanionOfEnum_after() throws Exception {
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChecker() { object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChecker() {
override fun analyze(data: PropertyInitializationInfoData, reporter: DiagnosticReporter, context: CheckerContext) { override fun analyze(data: PropertyInitializationInfoData, reporter: DiagnosticReporter, context: CheckerContext) {
data.checkPropertyAccesses(context, reporter) data.checkPropertyAccesses(isForClassInitialization = false, context, reporter)
} }
} }
@@ -44,15 +44,36 @@ val FirDeclaration.evaluatedInPlace: Boolean
else -> true // property initializer, etc. else -> true // property initializer, etc.
} }
@OptIn(SymbolInternals::class) /**
val FirPropertySymbol.requiresInitialization: Boolean * [isForClassInitialization] means that caller is interested in member property in the scope
get() = this !is FirSyntheticPropertySymbol && !hasInitializer && !hasExplicitBackingField && * of class initialization section. In this case the fact that property has initializer does
hasBackingField && fir.isCatchParameter != true * not mean that it's safe to access this property in any place:
*
* class A {
* val b = a // a is not initialized here
* val a = 10
* val c = a // but initialized here
* }
*/
fun PropertyInitializationInfoData.checkPropertyAccesses(context: CheckerContext, reporter: DiagnosticReporter) { @OptIn(SymbolInternals::class)
fun FirPropertySymbol.requiresInitialization(isForClassInitialization: Boolean): Boolean {
val hasImplicitBackingField = !hasExplicitBackingField && hasBackingField
return when {
this is FirSyntheticPropertySymbol -> false
isForClassInitialization -> hasDelegate || hasImplicitBackingField
else -> !hasInitializer && hasImplicitBackingField && fir.isCatchParameter != true
}
}
fun PropertyInitializationInfoData.checkPropertyAccesses(
isForClassInitialization: Boolean,
context: CheckerContext,
reporter: DiagnosticReporter
) {
// If a property has an initializer (or does not need one), then any reads are OK while any writes are OK // If a property has an initializer (or does not need one), then any reads are OK while any writes are OK
// if it's a `var` and bad if it's a `val`. `FirReassignmentAndInvisibleSetterChecker` does this without a CFG. // if it's a `var` and bad if it's a `val`. `FirReassignmentAndInvisibleSetterChecker` does this without a CFG.
val filtered = properties.filterTo(mutableSetOf()) { it.requiresInitialization } val filtered = properties.filterTo(mutableSetOf()) { it.requiresInitialization(isForClassInitialization) }
if (filtered.isEmpty()) return if (filtered.isEmpty()) return
checkPropertyAccesses(graph, filtered, context, reporter, null, mutableMapOf()) checkPropertyAccesses(graph, filtered, context, reporter, null, mutableMapOf())
@@ -73,6 +73,18 @@ class PropertyInitializationInfoCollector(
} }
} }
override fun visitPropertyInitializerExitNode(
node: PropertyInitializerExitNode,
data: PathAwareControlFlowInfo<PropertyInitializationInfo>
): PathAwareControlFlowInfo<PropertyInitializationInfo> {
// If member property initializer is empty (there are no nodes between enter and exit node)
// then property is not initialized in its declaration
// Otherwise it is
val dataForNode = visitNode(node, data)
if (node.firstPreviousNode is PropertyInitializerEnterNode) return dataForNode
return overwriteRange(dataForNode, node.fir.symbol, EventOccurrencesRange.EXACTLY_ONCE)
}
// -------------------------------------------------- // --------------------------------------------------
// Data flows of declared/assigned variables in loops // Data flows of declared/assigned variables in loops
// -------------------------------------------------- // --------------------------------------------------
@@ -47,12 +47,12 @@ object FirMemberPropertiesChecker : FirClassChecker() {
private fun FirClass.collectInitializationInfo(context: CheckerContext, reporter: DiagnosticReporter): PropertyInitializationInfo? { private fun FirClass.collectInitializationInfo(context: CheckerContext, reporter: DiagnosticReporter): PropertyInitializationInfo? {
val graph = (this as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph ?: return null val graph = (this as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph ?: return null
val memberPropertySymbols = declarations.mapNotNullTo(mutableSetOf()) { val memberPropertySymbols = declarations.mapNotNullTo(mutableSetOf()) {
(it.symbol as? FirPropertySymbol)?.takeIf { symbol -> symbol.requiresInitialization } (it.symbol as? FirPropertySymbol)?.takeIf { symbol -> symbol.requiresInitialization(isForClassInitialization = true) }
} }
if (memberPropertySymbols.isEmpty()) return null if (memberPropertySymbols.isEmpty()) return null
// TODO: merge with `FirPropertyInitializationAnalyzer` for fewer passes. // TODO: merge with `FirPropertyInitializationAnalyzer` for fewer passes.
val data = PropertyInitializationInfoData(memberPropertySymbols, symbol, graph) val data = PropertyInitializationInfoData(memberPropertySymbols, symbol, graph)
data.checkPropertyAccesses(context, reporter) data.checkPropertyAccesses(isForClassInitialization = true, context, reporter)
return data.getValue(graph.exitNode)[NormalPath] return data.getValue(graph.exitNode)[NormalPath]
} }
@@ -138,7 +138,8 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker()
if (property.isVar) return if (property.isVar) return
// Assignments of uninitialized `val`s must be checked via CFG, since the first one is OK. // Assignments of uninitialized `val`s must be checked via CFG, since the first one is OK.
// See `FirPropertyInitializationAnalyzer` for locals and `FirMemberPropertiesChecker` for backing fields in initializers. // See `FirPropertyInitializationAnalyzer` for locals and `FirMemberPropertiesChecker` for backing fields in initializers.
if (property.requiresInitialization && (property.isLocal || isInOwnersInitializer(expression.dispatchReceiver, context))) return if (property.isLocal && property.requiresInitialization(isForClassInitialization = false)) return
if (isInOwnersInitializer(expression.dispatchReceiver, context) && property.requiresInitialization(isForClassInitialization = true)) return
reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, property, context) reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, property, context)
} }
@@ -43,7 +43,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
} }
} }
private class ReassignedVariableCollector(val data: PropertyInitializationInfoData, ) : ControlFlowGraphVisitorVoid() { private class ReassignedVariableCollector(val data: PropertyInitializationInfoData) : ControlFlowGraphVisitorVoid() {
private val reassigned = mutableSetOf<FirPropertySymbol>() private val reassigned = mutableSetOf<FirPropertySymbol>()
override fun visitNode(node: CFGNode<*>) {} override fun visitNode(node: CFGNode<*>) {}
@@ -51,7 +51,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
override fun visitVariableAssignmentNode(node: VariableAssignmentNode) { override fun visitVariableAssignmentNode(node: VariableAssignmentNode) {
val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return
if (symbol.isVar && symbol.source?.kind !is KtFakeSourceElementKind && symbol in data.properties && if (symbol.isVar && symbol.source?.kind !is KtFakeSourceElementKind && symbol in data.properties &&
(!symbol.requiresInitialization || data.getValue(node).values.any { it[symbol]?.canBeRevisited() == true }) (!symbol.requiresInitialization(isForClassInitialization = data.graph.kind == ControlFlowGraph.Kind.Class) || data.getValue(node).values.any { it[symbol]?.canBeRevisited() == true })
) { ) {
reassigned.add(symbol) reassigned.add(symbol)
} }
@@ -255,8 +255,8 @@ class Outer() {
} }
class ForwardAccessToBackingField() { //kt-147 class ForwardAccessToBackingField() { //kt-147
val a = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>a<!> // error val a = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, UNINITIALIZED_VARIABLE!>a<!> // error
val b = c // error val b = <!UNINITIALIZED_VARIABLE!>c<!> // error
val c = 1 val c = 1
} }
@@ -0,0 +1,40 @@
// DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.KProperty
interface Delegate<V> {
operator fun getValue(thisRef: Any?, property: KProperty<*>): V = null!!
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {}
}
fun <V> delegate(): Delegate<V> = null!!
fun consume(x: Any?) {}
class A {
init {
consume(<!UNINITIALIZED_VARIABLE!>x<!>)
<!INITIALIZATION_BEFORE_DECLARATION!>x<!> = 10
}
val x: Int by delegate()
init {
<!VAL_REASSIGNMENT!>x<!> = 10
consume(x)
}
}
class B {
init {
consume(<!UNINITIALIZED_VARIABLE!>x<!>)
<!INITIALIZATION_BEFORE_DECLARATION!>x<!> = 10
}
var x: Int by delegate()
init {
x = 10
consume(x)
}
}
@@ -0,0 +1,40 @@
// DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.KProperty
interface Delegate<V> {
operator fun getValue(thisRef: Any?, property: KProperty<*>): V = null!!
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {}
}
fun <V> delegate(): Delegate<V> = null!!
fun consume(x: Any?) {}
class A {
init {
consume(<!UNINITIALIZED_VARIABLE!>x<!>)
<!VAL_REASSIGNMENT!>x<!> = 10
}
val x: Int by delegate()
init {
x = 10
consume(x)
}
}
class B {
init {
consume(<!UNINITIALIZED_VARIABLE!>x<!>)
<!INITIALIZATION_BEFORE_DECLARATION!>x<!> = 10
}
var x: Int by delegate()
init {
x = 10
consume(x)
}
}
@@ -1,4 +1,4 @@
// See also KT-10869: Accessing lazy properties from init causes IllegalArgumentException // ISSUE: KT-10869, KT-56682
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@@ -9,14 +9,14 @@ class CustomDelegate {
class Kaboom() { class Kaboom() {
// Here and below we should have errors for simple AND delegated // Here and below we should have errors for simple AND delegated
init { init {
delegated.hashCode() <!UNINITIALIZED_VARIABLE!>delegated<!>.hashCode()
simple.hashCode() <!UNINITIALIZED_VARIABLE!>simple<!>.hashCode()
withGetter.hashCode() withGetter.hashCode()
} }
val other = delegated val other = <!UNINITIALIZED_VARIABLE!>delegated<!>
val another = simple val another = <!UNINITIALIZED_VARIABLE!>simple<!>
val something = withGetter val something = withGetter
@@ -1,4 +1,4 @@
// See also KT-10869: Accessing lazy properties from init causes IllegalArgumentException // ISSUE: KT-10869, KT-56682
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@@ -1,20 +0,0 @@
//KT-897 Don't allow assignment to a property before it is defined
package kt897
class A() {
init {
<!INITIALIZATION_BEFORE_DECLARATION, VAL_REASSIGNMENT!>i<!> = 11
}
val i : Int? = null // must be an error
init {
<!INITIALIZATION_BEFORE_DECLARATION!>j<!> = 1
}
var j : Int = 2
init {
<!INITIALIZATION_BEFORE_DECLARATION!>k<!> = 3
}
val k : Int
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
//KT-897 Don't allow assignment to a property before it is defined //KT-897 Don't allow assignment to a property before it is defined
package kt897 package kt897
@@ -0,0 +1,87 @@
fun println(obj: Any?) = obj
class Demo0 {
private val some = object {
fun foo() {
println(state)
}
}
private var state: Boolean = true
}
class Demo1 {
private val some = object {
fun foo() {
if (state)
state = true
println(state)
}
}
private var state: Boolean = true
}
class Demo1A {
fun foo() {
if (state)
state = true
println(state)
}
private var state: Boolean = true
}
class Demo2 {
private val some = object {
fun foo() {
if (state)
state = true
else
state = false
println(state)
}
}
private var state: Boolean = true
}
class Demo3 {
private val some = run {
if (state)
state = true
println(state)
}
private var state: Boolean = true
}
fun <T> exec(f: () -> T): T = f()
class Demo4 {
private val some = exec {
if (<!UNINITIALIZED_VARIABLE!>state<!>)
state = true
println(<!UNINITIALIZED_VARIABLE!>state<!>)
}
private var state: Boolean = true
}
class Demo5 {
private var state: Boolean = true
private val some = object {
fun foo() {
if (state)
state = true
println(state)
}
}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
fun println(obj: Any?) = obj fun println(obj: Any?) = obj
class Demo0 { class Demo0 {
@@ -11,22 +11,22 @@ class TestFunctionLiteral {
open class A(val a: A) open class A(val a: A)
class TestObjectLiteral { class TestObjectLiteral {
val obj: A = object: A(obj) { val obj: A = object: A(<!UNINITIALIZED_VARIABLE!>obj<!>) {
init { init {
val x = obj val x = <!UNINITIALIZED_VARIABLE!>obj<!>
} }
fun foo() { fun foo() {
val y = obj val y = obj
} }
} }
val obj1: A = l@ ( object: A(obj1) { val obj1: A = l@ ( object: A(<!UNINITIALIZED_VARIABLE!>obj1<!>) {
init { init {
val x = obj1 val x = <!UNINITIALIZED_VARIABLE!>obj1<!>
} }
fun foo() = obj1 fun foo() = obj1
}) })
} }
class TestOther { class TestOther {
val x: Int = x + 1 val x: Int = <!UNINITIALIZED_VARIABLE!>x<!> + 1
} }
@@ -4,8 +4,8 @@ val a : Int = b
val b : Int = a + b val b : Int = a + b
class C { class C {
val a : Int = b val a : Int = <!UNINITIALIZED_VARIABLE!>b<!>
val b : Int = a + b val b : Int = a + <!UNINITIALIZED_VARIABLE!>b<!>
} }
fun foo() { fun foo() {
@@ -0,0 +1,18 @@
// FIR_IDENTICAL
// ISSUE: KT-56678
class A {
val b = <!UNINITIALIZED_VARIABLE!>a<!>
val a = 1
val c = a
}
class B {
val b = <!UNINITIALIZED_VARIABLE!>a<!>
val a: Int
val c = <!UNINITIALIZED_VARIABLE!>a<!>
init {
a = 1
}
val d = a
}
@@ -4,7 +4,7 @@
object DelegateTest { object DelegateTest {
var result = "" var result = ""
val f by lazy { val f by lazy {
result += <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: cycle"), TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>f<!>.toString() // Compiler crash result += <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: cycle"), TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, UNINITIALIZED_VARIABLE!>f<!>.toString() // Compiler crash
"hello" "hello"
} }
} }
@@ -12,7 +12,7 @@ object DelegateTest {
object DelegateTest2 { object DelegateTest2 {
var result = "" var result = ""
val f by lazy { val f by lazy {
result += <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: cycle"), TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>f<!> result += <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: cycle"), TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, UNINITIALIZED_VARIABLE!>f<!>
"hello" "hello"
} }
} }
@@ -5,7 +5,7 @@
object DelegateTest { object DelegateTest {
var result = "" var result = ""
val f by lazy { val f by lazy {
result += <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: cycle"), TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>f<!>.toString() // Compiler crash result += <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: cycle"), TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, UNINITIALIZED_VARIABLE!>f<!>.toString() // Compiler crash
"hello" "hello"
} }
} }
@@ -13,7 +13,7 @@ object DelegateTest {
object DelegateTest2 { object DelegateTest2 {
var result = "" var result = ""
val f by lazy { val f by lazy {
result += <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: cycle"), TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>f<!> result += <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: cycle"), TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, UNINITIALIZED_VARIABLE!>f<!>
"hello" "hello"
} }
} }
@@ -3,7 +3,7 @@
object DelegateTest { object DelegateTest {
var result = "" var result = ""
val f by lazy { val f by lazy {
result += <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>f<!>.toString() // Compiler crash result += <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, UNINITIALIZED_VARIABLE!>f<!>.toString() // Compiler crash
"hello" "hello"
} }
} }
@@ -3,7 +3,7 @@
class Test { class Test {
private val y = object { private val y = object {
val a = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>y<!>; val a = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, UNINITIALIZED_VARIABLE!>y<!>;
} }
val z = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>y.a<!>; val z = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>y.a<!>;
@@ -17,9 +17,9 @@ object A {
class Test2 { class Test2 {
private val a = object { private val a = object {
init { init {
b + 1 <!UNINITIALIZED_VARIABLE!>b<!> + 1
} }
val x = b val x = <!UNINITIALIZED_VARIABLE!>b<!>
val y = 1 val y = 1
} }
@@ -12,7 +12,7 @@ fun bar2() = {
//properties //properties
//in a class //in a class
class A() { class A() {
val x = { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>x<!> } val x = { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, UNINITIALIZED_VARIABLE!>x<!> }
} }
//in a package //in a package
@@ -3,7 +3,7 @@ class A(val w: Int) {
val x: Int val x: Int
val useUnitialized = <!UNINITIALIZED_VARIABLE!>x<!> + val useUnitialized = <!UNINITIALIZED_VARIABLE!>x<!> +
<!UNINITIALIZED_VARIABLE!>y<!> + <!UNINITIALIZED_VARIABLE!>y<!> +
v <!UNINITIALIZED_VARIABLE!>v<!>
var y: Int var y: Int
val v = -1 val v = -1
val useInitialized = useUnitialized + v + w val useInitialized = useUnitialized + v + w
@@ -3,7 +3,7 @@ class A {
val x: Int val x: Int
val useUnitialized = <!UNINITIALIZED_VARIABLE!>x<!> + // reported on each secondary constructor val useUnitialized = <!UNINITIALIZED_VARIABLE!>x<!> + // reported on each secondary constructor
<!UNINITIALIZED_VARIABLE!>y<!> + <!UNINITIALIZED_VARIABLE!>y<!> +
v <!UNINITIALIZED_VARIABLE!>v<!>
var y: Int var y: Int
val v = -1 val v = -1
@@ -5702,6 +5702,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt"); runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt");
} }
@Test
@TestMetadata("delegatedMemberProperyWriteInInit.kt")
public void testDelegatedMemberProperyWriteInInit() throws Exception {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/delegatedMemberProperyWriteInInit.kt");
}
@Test @Test
@TestMetadata("delegatedPropertyEarlyAccess.kt") @TestMetadata("delegatedPropertyEarlyAccess.kt")
public void testDelegatedPropertyEarlyAccess() throws Exception { public void testDelegatedPropertyEarlyAccess() throws Exception {
@@ -6122,6 +6128,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt"); runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt");
} }
@Test
@TestMetadata("uninintializedProperyWithDirectAndDelayedInitialization.kt")
public void testUninintializedProperyWithDirectAndDelayedInitialization() throws Exception {
runTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/uninintializedProperyWithDirectAndDelayedInitialization.kt");
}
@Test @Test
@TestMetadata("uninitializedCompanionOfEnum_after.kt") @TestMetadata("uninitializedCompanionOfEnum_after.kt")
public void testUninitializedCompanionOfEnum_after() throws Exception { public void testUninitializedCompanionOfEnum_after() throws Exception {