[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
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
||||
@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
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
||||
@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.
|
||||
LOCAL_VAR(null),
|
||||
|
||||
// Smartcast is always unsafe regardless of usage.
|
||||
EXPECT_PROPERTY(SmartcastStability.EXPECT_PROPERTY),
|
||||
|
||||
// Open or custom getter.
|
||||
// Smartcast is always unsafe regardless of usage.
|
||||
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.FirRegularClass
|
||||
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.modality
|
||||
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 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 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
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
@@ -17,6 +17,9 @@ enum class SmartcastStability(private val str: String, val description: String =
|
||||
// Smart casts are completely safe
|
||||
STABLE_VALUE("stable val"),
|
||||
|
||||
// Smart casts are not safe
|
||||
EXPECT_PROPERTY("expect property"),
|
||||
|
||||
// Member value with open / custom getter
|
||||
// Smart casts are not safe
|
||||
PROPERTY_WITH_GETTER("custom getter", "property that has open or custom getter"),
|
||||
|
||||
Reference in New Issue
Block a user