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 d72e3b666e4..64b095d7eb6 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 @@ -96,8 +96,11 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses( doNotReportConstantUninitialized: Boolean, scopes: MutableMap, ) { - fun FirQualifiedAccessExpression.hasCorrectReceiver() = - (dispatchReceiver?.unwrapSmartcastExpression() as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver + fun FirQualifiedAccessExpression.hasMatchingReceiver(): Boolean { + val expression = dispatchReceiver?.unwrapSmartcastExpression() + return (expression as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver || + (expression as? FirResolvedQualifier)?.symbol == receiver + } for (node in graph.nodes) { when { @@ -115,7 +118,7 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses( node is VariableAssignmentNode -> { val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: continue - if (!symbol.isVal || node.fir.unwrapLValue()?.hasCorrectReceiver() != true || symbol !in properties) continue + if (!symbol.isVal || node.fir.unwrapLValue()?.hasMatchingReceiver() != true || symbol !in properties) continue if (getValue(node).values.any { it[symbol]?.canBeRevisited() == true }) { reporter.reportOn(node.fir.lValue.source, FirErrors.VAL_REASSIGNMENT, symbol, context) @@ -133,7 +136,7 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses( if (node.fir.resolvedType.hasDiagnosticKind(DiagnosticKind.RecursionInImplicitTypes)) continue val symbol = node.fir.calleeReference.toResolvedPropertySymbol() ?: continue if (doNotReportConstantUninitialized && symbol.isConst) continue - if (!symbol.isLateInit && !symbol.isExternal && node.fir.hasCorrectReceiver() && symbol in properties && + if (!symbol.isLateInit && !symbol.isExternal && node.fir.hasMatchingReceiver() && symbol in properties && getValue(node).values.any { it[symbol]?.isDefinitelyVisited() != true } ) { reporter.reportOn(node.fir.source, FirErrors.UNINITIALIZED_VARIABLE, symbol, context) diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.fir.kt index c5ebffdee11..e990a33bb49 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.fir.kt @@ -1,5 +1,6 @@ -// See KT-15566 +// WITH_STDLIB // NI_EXPECTED_FILE +// ISSUE: KT-15566, KT-56489 import DefaultHttpClient.client @@ -9,7 +10,7 @@ class HttpClientImpl : HttpClient // Below we should have initialization error for both (!) delegates -object DefaultHttpClient : HttpClient by client { +object DefaultHttpClient : HttpClient by client { val client = HttpClientImpl() } @@ -22,15 +23,10 @@ object DefaultHttpClientWithFun : HttpClient by fClient() { private fun fClient() = HttpClientImpl() -private fun lazy(init: () -> T): kotlin.Lazy { - init() - null!! -} - object DefaultHttpClientWithBy : HttpClient by client { val client by lazy { HttpClientImpl() } } -object DefaultFqHttpClient : HttpClient by DefaultFqHttpClient.client { +object DefaultFqHttpClient : HttpClient by DefaultFqHttpClient.client { val client = HttpClientImpl() } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.kt index a2c58cd474c..dc30d7d77cf 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.kt @@ -1,5 +1,6 @@ -// See KT-15566 +// WITH_STDLIB // NI_EXPECTED_FILE +// ISSUE: KT-15566, KT-56489 import DefaultHttpClient.client @@ -22,15 +23,10 @@ object DefaultHttpClientWithFun : HttpClient by fClient() { private fun fClient() = HttpClientImpl() -private fun lazy(init: () -> T): kotlin.Lazy { - init() - null!! -} - object DefaultHttpClientWithBy : HttpClient by client { val client by lazy { HttpClientImpl() } } object DefaultFqHttpClient : HttpClient by DefaultFqHttpClient.client { val client = HttpClientImpl() -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.ni.txt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.ni.txt index 11d3a97eac2..74d68bf74ee 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.ni.txt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/fieldAsClassDelegate.ni.txt @@ -1,7 +1,6 @@ package private fun fClient(): HttpClientImpl -private fun lazy(/*0*/ init: () -> T): [Error type: Unresolved type for kotlin.Lazy] public object DefaultFqHttpClient : HttpClient { private constructor DefaultFqHttpClient() @@ -21,7 +20,7 @@ public object DefaultHttpClient : HttpClient { public object DefaultHttpClientWithBy : HttpClient { private constructor DefaultHttpClientWithBy() - public final val client: [Error type: Error delegation type for lazy { HttpClientImpl() }] + public final val client: HttpClientImpl 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