[K2] Prohibit smart casts for 'expect' properties
^KT-61340
This commit is contained in:
committed by
Space Team
parent
e4ea733482
commit
e3bab4a7da
+22
@@ -1723,6 +1723,28 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/smartCasts")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class SmartCasts {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInSmartCasts() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/smartCasts"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61340_commonCode.kt")
|
||||||
|
public void testKt61340_commonCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/smartCasts/kt61340_commonCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61340_platformCode.kt")
|
||||||
|
public void testKt61340_platformCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/smartCasts/kt61340_platformCode.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+22
@@ -1723,6 +1723,28 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/smartCasts")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class SmartCasts {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInSmartCasts() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/smartCasts"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61340_commonCode.kt")
|
||||||
|
public void testKt61340_commonCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/smartCasts/kt61340_commonCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61340_platformCode.kt")
|
||||||
|
public void testKt61340_platformCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/smartCasts/kt61340_platformCode.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ enum class PropertyStability(val impliedSmartcastStability: SmartcastStability?)
|
|||||||
// Smartcast may or may not be safe, depending on whether there are concurrent writes to this local variable.
|
// Smartcast may or may not be safe, depending on whether there are concurrent writes to this local variable.
|
||||||
LOCAL_VAR(null),
|
LOCAL_VAR(null),
|
||||||
|
|
||||||
|
// Smartcast is always unsafe regardless of usage.
|
||||||
|
EXPECT_PROPERTY(SmartcastStability.EXPECT_PROPERTY),
|
||||||
|
|
||||||
// Open or custom getter.
|
// Open or custom getter.
|
||||||
// Smartcast is always unsafe regardless of usage.
|
// Smartcast is always unsafe regardless of usage.
|
||||||
PROPERTY_WITH_GETTER(SmartcastStability.PROPERTY_WITH_GETTER),
|
PROPERTY_WITH_GETTER(SmartcastStability.PROPERTY_WITH_GETTER),
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||||
@@ -165,6 +166,7 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
|
|||||||
is FirFunctionSymbol<*>, is FirClassSymbol<*> -> return PropertyStability.STABLE_VALUE
|
is FirFunctionSymbol<*>, is FirClassSymbol<*> -> return PropertyStability.STABLE_VALUE
|
||||||
is FirBackingFieldSymbol -> return if (isVal) PropertyStability.STABLE_VALUE else PropertyStability.MUTABLE_PROPERTY
|
is FirBackingFieldSymbol -> return if (isVal) PropertyStability.STABLE_VALUE else PropertyStability.MUTABLE_PROPERTY
|
||||||
}
|
}
|
||||||
|
if (this is FirCallableSymbol && this.isExpect) return PropertyStability.EXPECT_PROPERTY
|
||||||
if (this !is FirVariableSymbol<*>) return null
|
if (this !is FirVariableSymbol<*>) return null
|
||||||
if (this is FirFieldSymbol && !this.isFinal) return PropertyStability.MUTABLE_PROPERTY
|
if (this is FirFieldSymbol && !this.isFinal) return PropertyStability.MUTABLE_PROPERTY
|
||||||
|
|
||||||
|
|||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
|
||||||
|
expect val foo: Any
|
||||||
|
|
||||||
|
expect class Bar() {
|
||||||
|
val bus: Any
|
||||||
|
}
|
||||||
|
|
||||||
|
fun common() {
|
||||||
|
if (foo is String) <!SMARTCAST_IMPOSSIBLE!>foo<!>.length
|
||||||
|
|
||||||
|
val bar = Bar()
|
||||||
|
if (bar.bus is String) <!SMARTCAST_IMPOSSIBLE!>bar.bus<!>.length
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual val foo: Any = 2
|
||||||
|
|
||||||
|
actual class Bar actual constructor() {
|
||||||
|
actual val bus: Any
|
||||||
|
get() = "bus"
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
|
||||||
|
expect val foo: Any
|
||||||
|
|
||||||
|
expect class Bar() {
|
||||||
|
val bus: Any
|
||||||
|
}
|
||||||
|
|
||||||
|
fun common() {
|
||||||
|
if (foo is String) foo.length
|
||||||
|
|
||||||
|
val bar = Bar()
|
||||||
|
if (bar.bus is String) <!SMARTCAST_IMPOSSIBLE{JVM}!>bar.bus<!>.length
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual val foo: Any = 2
|
||||||
|
|
||||||
|
actual class Bar actual constructor() {
|
||||||
|
actual val bus: Any
|
||||||
|
get() = "bus"
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
|
||||||
|
expect val foo: Any
|
||||||
|
|
||||||
|
expect class Bar() {
|
||||||
|
val bus: Any
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual val foo: Any = 2
|
||||||
|
|
||||||
|
actual class Bar actual constructor() {
|
||||||
|
actual val bus: Any
|
||||||
|
get() = "bus"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun platform() {
|
||||||
|
if (foo is String) foo.length
|
||||||
|
|
||||||
|
val bar = Bar()
|
||||||
|
if (bar.bus is String) <!SMARTCAST_IMPOSSIBLE!>bar.bus<!>.length
|
||||||
|
}
|
||||||
Generated
+22
@@ -24892,6 +24892,28 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/smartCasts")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class SmartCasts {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInSmartCasts() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/smartCasts"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61340_commonCode.kt")
|
||||||
|
public void testKt61340_commonCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/smartCasts/kt61340_commonCode.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt61340_platformCode.kt")
|
||||||
|
public void testKt61340_platformCode() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/smartCasts/kt61340_platformCode.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ enum class SmartcastStability(private val str: String, val description: String =
|
|||||||
// Smart casts are completely safe
|
// Smart casts are completely safe
|
||||||
STABLE_VALUE("stable val"),
|
STABLE_VALUE("stable val"),
|
||||||
|
|
||||||
|
// Smart casts are not safe
|
||||||
|
EXPECT_PROPERTY("expect property"),
|
||||||
|
|
||||||
// Member value with open / custom getter
|
// Member value with open / custom getter
|
||||||
// Smart casts are not safe
|
// Smart casts are not safe
|
||||||
PROPERTY_WITH_GETTER("custom getter", "property that has open or custom getter"),
|
PROPERTY_WITH_GETTER("custom getter", "property that has open or custom getter"),
|
||||||
|
|||||||
Reference in New Issue
Block a user