From 74fa6fc12c2096659177aa2b35e133b818b908fd Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Wed, 17 Jan 2024 15:16:08 +0100 Subject: [PATCH] [k2, dfa] Smartcasts are not allowed on FirJavaField from other module Handle case with FirField properly. Previously the code was returning STABLE_VALUE in that case. Note that in fact the changed 'when' branch expects only FirJavaField, as FirFieldImpl should be handled by FirBackingFieldSymbol-check at the beginning of the method. However, it is impossible to refer to FirJavaField directly due to module visibility Enumerate all cases more carefully via exhaustive 'when', it's more readable and will prevent potential issues in future in case more subclasses are added. ^KT-58279 Fixed --- .../fir/resolve/dfa/VariableStorageImpl.kt | 52 ++++++++++++------- .../staticJavaFieldFromOtherModule.kt | 6 +-- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorageImpl.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorageImpl.kt index 497a02d0a0a..8cd15f7bd61 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorageImpl.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorageImpl.kt @@ -9,14 +9,9 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession -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.* 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 +import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.originalOrSelf @@ -170,7 +165,25 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() { if (this !is FirVariableSymbol<*>) return null if (this is FirFieldSymbol && !this.isFinal) return PropertyStability.MUTABLE_PROPERTY - val property = this.fir as? FirProperty ?: return PropertyStability.STABLE_VALUE + val property = when (val variable = this.fir) { // intentionally exhaustive 'when' + is FirEnumEntry, is FirErrorProperty, is FirValueParameter -> return PropertyStability.STABLE_VALUE + + // NB: FirJavaField is expected here. FirFieldImpl should've been handled by FirBackingFieldSymbol check above + is FirField -> { + if (variable.isJava) + return variable.determineStabilityByModule() + else + errorWithAttachment("Expected to handle non-Java FirFields via symbol-based checks") { + withFirEntry("fir", variable) + } + } + + is FirBackingField -> errorWithAttachment("Expected to handle Backing Field entirely via symbol-based checks") { + withFirEntry("fir", variable) + } + + is FirProperty -> variable + } return when { property.delegate != null -> PropertyStability.DELEGATED_PROPERTY @@ -192,16 +205,19 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() { } } } - else -> { - val propertyModuleData = property.originalOrSelf().moduleData - val currentModuleData = session.moduleData - when (propertyModuleData) { - currentModuleData, - in currentModuleData.friendDependencies, - in currentModuleData.dependsOnDependencies -> PropertyStability.STABLE_VALUE - else -> PropertyStability.ALIEN_PUBLIC_PROPERTY - } - } + else -> property.determineStabilityByModule() + } + } + + private fun FirVariable.determineStabilityByModule(): PropertyStability { + val propertyModuleData = originalOrSelf().moduleData + val currentModuleData = session.moduleData + return when (propertyModuleData) { + currentModuleData, + in currentModuleData.friendDependencies, + in currentModuleData.dependsOnDependencies, + -> PropertyStability.STABLE_VALUE + else -> PropertyStability.ALIEN_PUBLIC_PROPERTY } } } diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/staticJavaFieldFromOtherModule.kt b/compiler/testData/diagnostics/tests/smartCasts/variables/staticJavaFieldFromOtherModule.kt index 4764ba7c8a9..82ab73fd28b 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/staticJavaFieldFromOtherModule.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/staticJavaFieldFromOtherModule.kt @@ -11,8 +11,8 @@ public class J { // MODULE: app(lib) fun isCast() { if (J.staticFinalJava is String) { - J.staticFinalJava.length - (J.staticFinalJava as String).length + J.staticFinalJava.length + (J.staticFinalJava as String).length } if (J.staticNonFinalJava is String) { @@ -23,7 +23,7 @@ fun isCast() { fun asCast() { J.staticFinalJava as String - J.staticFinalJava.length + J.staticFinalJava.length J.staticNonFinalJava as String J.staticNonFinalJava.length