diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java index ca7ef011213..88c166100b9 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java @@ -1212,6 +1212,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis public void testReassignOfNonMemberProperty_lateInitialization() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/cfa/reassignOfNonMemberProperty_lateInitialization.kt"); } + + @Test + @TestMetadata("smartcastOnThisDuringClassInitialization.kt") + public void testSmartcastOnThisDuringClassInitialization() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.kt"); + } } @Nested diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index a3d5fdf5de6..07cbd6bc388 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -1045,6 +1045,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract public void testReassignOfNonMemberProperty_lateInitialization() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/cfa/reassignOfNonMemberProperty_lateInitialization.kt"); } + + @TestMetadata("smartcastOnThisDuringClassInitialization.kt") + public void testSmartcastOnThisDuringClassInitialization() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.kt"); + } } @TestMetadata("compiler/fir/analysis-tests/testData/resolve/cfg") diff --git a/compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.fir.txt new file mode 100644 index 00000000000..036904a75ba --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.fir.txt @@ -0,0 +1,17 @@ +FILE: smartcastOnThisDuringClassInitialization.kt + public abstract interface I : R|kotlin/Any| { + } + public open class Some : R|kotlin/Any| { + public constructor(): R|Some| { + super() + } + + public final val x: R|kotlin/Int| + public get(): R|kotlin/Int| + + init { + (this@R|/Some| as R|I|) + this@R|/Some|.R|/Some.x| = Int(1) + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.kt b/compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.kt new file mode 100644 index 00000000000..d450c98948a --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.kt @@ -0,0 +1,11 @@ +// ISSUE: KT-56863 +interface I + +open class Some { + val x: Int + + init { + this as I + x = 1 + } +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java index 3e8a9fbf2f9..70589815801 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java @@ -1212,6 +1212,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi public void testReassignOfNonMemberProperty_lateInitialization() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/cfa/reassignOfNonMemberProperty_lateInitialization.kt"); } + + @Test + @TestMetadata("smartcastOnThisDuringClassInitialization.kt") + public void testSmartcastOnThisDuringClassInitialization() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.kt"); + } } @Nested diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java index a89d87300ad..fe5a1a02bdb 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java @@ -1212,6 +1212,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest public void testReassignOfNonMemberProperty_lateInitialization() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/cfa/reassignOfNonMemberProperty_lateInitialization.kt"); } + + @Test + @TestMetadata("smartcastOnThisDuringClassInitialization.kt") + public void testSmartcastOnThisDuringClassInitialization() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/cfa/smartcastOnThisDuringClassInitialization.kt"); + } } @Nested 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 3f032cb2f6d..0e4beee8529 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 @@ -18,10 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField import org.jetbrains.kotlin.fir.declarations.utils.isLateInit -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression -import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression -import org.jetbrains.kotlin.fir.expressions.calleeReference -import org.jetbrains.kotlin.fir.expressions.unwrapLValue +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* @@ -95,7 +92,7 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses( scopes: MutableMap ) { fun FirQualifiedAccessExpression.hasCorrectReceiver() = - (dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver + (dispatchReceiver.unwrapSmartcastExpression() as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver for (node in graph.nodes) { when { 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 82936c77fd8..7bf575e52bc 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 @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.calleeReference import org.jetbrains.kotlin.fir.expressions.dispatchReceiver +import org.jetbrains.kotlin.fir.expressions.unwrapSmartcastExpression import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -51,7 +52,7 @@ class PropertyInitializationInfoCollector( data: PathAwarePropertyInitializationInfo ): PathAwarePropertyInitializationInfo { val dataForNode = visitNode(node, data) - val receiver = (node.fir.dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol + val receiver = (node.fir.dispatchReceiver.unwrapSmartcastExpression() as? FirThisReceiverExpression)?.calleeReference?.boundSymbol if (receiver != expectedReceiver) return dataForNode val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return dataForNode if (symbol !in localProperties) return dataForNode diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt index efb2f2942e0..2267359dbf7 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt @@ -139,7 +139,10 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker() // 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. if (property.isLocal && property.requiresInitialization(isForClassInitialization = false)) return - if (isInOwnersInitializer(expression.dispatchReceiver, context) && property.requiresInitialization(isForClassInitialization = true)) return + if ( + isInOwnersInitializer(expression.dispatchReceiver.unwrapSmartcastExpression(), context) + && property.requiresInitialization(isForClassInitialization = true) + ) return reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, property, context) }