[FIR] Unwrap smartcast on dispatch receiver in CFA for class initialization
^KT-56863 Fixed
This commit is contained in:
committed by
Space Team
parent
bb368bd191
commit
ae07d0e9ce
+6
@@ -1212,6 +1212,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
|||||||
public void testReassignOfNonMemberProperty_lateInitialization() throws Exception {
|
public void testReassignOfNonMemberProperty_lateInitialization() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/cfa/reassignOfNonMemberProperty_lateInitialization.kt");
|
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
|
@Nested
|
||||||
|
|||||||
+5
@@ -1045,6 +1045,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
|||||||
public void testReassignOfNonMemberProperty_lateInitialization() throws Exception {
|
public void testReassignOfNonMemberProperty_lateInitialization() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/cfa/reassignOfNonMemberProperty_lateInitialization.kt");
|
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")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/cfg")
|
||||||
|
|||||||
Vendored
+17
@@ -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<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// ISSUE: KT-56863
|
||||||
|
interface I
|
||||||
|
|
||||||
|
open class Some {
|
||||||
|
val x: Int
|
||||||
|
|
||||||
|
init {
|
||||||
|
this as I
|
||||||
|
x = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -1212,6 +1212,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
|
|||||||
public void testReassignOfNonMemberProperty_lateInitialization() throws Exception {
|
public void testReassignOfNonMemberProperty_lateInitialization() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/cfa/reassignOfNonMemberProperty_lateInitialization.kt");
|
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
|
@Nested
|
||||||
|
|||||||
+6
@@ -1212,6 +1212,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
|
|||||||
public void testReassignOfNonMemberProperty_lateInitialization() throws Exception {
|
public void testReassignOfNonMemberProperty_lateInitialization() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/cfa/reassignOfNonMemberProperty_lateInitialization.kt");
|
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
|
@Nested
|
||||||
|
|||||||
+2
-5
@@ -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.hasBackingField
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField
|
import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isLateInit
|
import org.jetbrains.kotlin.fir.declarations.utils.isLateInit
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
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.isCatchParameter
|
import org.jetbrains.kotlin.fir.isCatchParameter
|
||||||
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
|
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||||
@@ -95,7 +92,7 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses(
|
|||||||
scopes: MutableMap<FirPropertySymbol, FirDeclaration?>
|
scopes: MutableMap<FirPropertySymbol, FirDeclaration?>
|
||||||
) {
|
) {
|
||||||
fun FirQualifiedAccessExpression.hasCorrectReceiver() =
|
fun FirQualifiedAccessExpression.hasCorrectReceiver() =
|
||||||
(dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver
|
(dispatchReceiver.unwrapSmartcastExpression() as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver
|
||||||
|
|
||||||
for (node in graph.nodes) {
|
for (node in graph.nodes) {
|
||||||
when {
|
when {
|
||||||
|
|||||||
+2
-1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
|||||||
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
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.unwrapSmartcastExpression
|
||||||
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
|
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
@@ -51,7 +52,7 @@ class PropertyInitializationInfoCollector(
|
|||||||
data: PathAwarePropertyInitializationInfo
|
data: PathAwarePropertyInitializationInfo
|
||||||
): PathAwarePropertyInitializationInfo {
|
): PathAwarePropertyInitializationInfo {
|
||||||
val dataForNode = visitNode(node, data)
|
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
|
if (receiver != expectedReceiver) return dataForNode
|
||||||
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
|
||||||
|
|||||||
+4
-1
@@ -139,7 +139,10 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker()
|
|||||||
// 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.isLocal && property.requiresInitialization(isForClassInitialization = false)) return
|
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)
|
reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, property, context)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user