K2: Put boolean DFA variables under a feature flag
^KT-62547 Fixed I also tested the commit by disabling DfaBooleanVariables in all tests and checking what tests will fail I didn't find anything that worked in K1, but doesn't work in K2 with DfaBooleanVariables disabled Related tests: - DiagnosticCompilerTestFirTestdataTestGenerated$Resolve$Smartcasts - LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated$Resolve$Smartcasts - PreFirIdeSpecTestGenerated$NotLinked$Dfa - DiagnosticCompilerTestFE10TestdataTestGenerated$Tests$SmartCasts - FirPsiDiagnosticTestGenerated$Resolve$Expresssions.testSyntheticSmartCast
This commit is contained in:
+6
@@ -34962,6 +34962,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disableDfaBooleanVariables.kt")
|
||||||
|
public void testDisableDfaBooleanVariables() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/smartCasts/disableDfaBooleanVariables.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("doubleLambdaArgument.kt")
|
@TestMetadata("doubleLambdaArgument.kt")
|
||||||
public void testDoubleLambdaArgument() throws Exception {
|
public void testDoubleLambdaArgument() throws Exception {
|
||||||
|
|||||||
+6
@@ -34962,6 +34962,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
|||||||
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disableDfaBooleanVariables.kt")
|
||||||
|
public void testDisableDfaBooleanVariables() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/smartCasts/disableDfaBooleanVariables.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("doubleLambdaArgument.kt")
|
@TestMetadata("doubleLambdaArgument.kt")
|
||||||
public void testDoubleLambdaArgument() throws Exception {
|
public void testDoubleLambdaArgument() throws Exception {
|
||||||
|
|||||||
+6
@@ -32606,6 +32606,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
|||||||
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disableDfaBooleanVariables.kt")
|
||||||
|
public void testDisableDfaBooleanVariables() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/smartCasts/disableDfaBooleanVariables.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("doubleLambdaArgument.kt")
|
@TestMetadata("doubleLambdaArgument.kt")
|
||||||
public void testDoubleLambdaArgument() throws Exception {
|
public void testDoubleLambdaArgument() throws Exception {
|
||||||
|
|||||||
+6
@@ -32732,6 +32732,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disableDfaBooleanVariables.kt")
|
||||||
|
public void testDisableDfaBooleanVariables() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/smartCasts/disableDfaBooleanVariables.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("doubleLambdaArgument.kt")
|
@TestMetadata("doubleLambdaArgument.kt")
|
||||||
public void testDoubleLambdaArgument() throws Exception {
|
public void testDoubleLambdaArgument() throws Exception {
|
||||||
|
|||||||
+8
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.resolve.dfa
|
package org.jetbrains.kotlin.fir.resolve.dfa
|
||||||
|
|
||||||
import kotlinx.collections.immutable.toPersistentSet
|
import kotlinx.collections.immutable.toPersistentSet
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.contracts.description.LogicOperationKind
|
import org.jetbrains.kotlin.contracts.description.LogicOperationKind
|
||||||
import org.jetbrains.kotlin.contracts.description.canBeRevisited
|
import org.jetbrains.kotlin.contracts.description.canBeRevisited
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
@@ -1086,9 +1087,15 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
// if (b != null) { /* a != null, but a.x could have changed */ }
|
// if (b != null) { /* a != null, but a.x could have changed */ }
|
||||||
logicSystem.translateVariableFromConditionInStatements(flow, initializerVariable, propertyVariable)
|
logicSystem.translateVariableFromConditionInStatements(flow, initializerVariable, propertyVariable)
|
||||||
}
|
}
|
||||||
} else if (initializerVariable != null && propertyVariable.isStable) {
|
} else if (initializerVariable != null && propertyVariable.isStable &&
|
||||||
|
(components.session.languageVersionSettings.supportsFeature(LanguageFeature.DfaBooleanVariables) ||
|
||||||
|
!initializer.resolvedType.isBoolean)
|
||||||
|
) {
|
||||||
// val b = x is String
|
// val b = x is String
|
||||||
// if (b) { /* x is String */ }
|
// if (b) { /* x is String */ }
|
||||||
|
|
||||||
|
// val b = x?.foo() // `x?.foo()` is synthetic
|
||||||
|
// if (b != null) { /* x != null */ }
|
||||||
logicSystem.translateVariableFromConditionInStatements(flow, initializerVariable, propertyVariable)
|
logicSystem.translateVariableFromConditionInStatements(flow, initializerVariable, propertyVariable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
|
||||||
|
// LANGUAGE:-DfaBooleanVariables
|
||||||
|
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
fun test1() {
|
||||||
|
val nullableString: String? = ""
|
||||||
|
val test = nullableString != null
|
||||||
|
if (test) nullableString<!UNSAFE_CALL!>.<!>length
|
||||||
|
if (nullableString != null) nullableString.length
|
||||||
|
}
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val a: String? = ""
|
||||||
|
}
|
||||||
|
fun test3(a: A) {
|
||||||
|
val test = a.a != null
|
||||||
|
if (test) a.a<!UNSAFE_CALL!>.<!>length
|
||||||
|
if (a.a != null) {
|
||||||
|
a.a.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test4() {
|
||||||
|
val nullableAny: Any? = ""
|
||||||
|
val test = nullableAny != null && nullableAny is String?
|
||||||
|
if (test) nullableAny.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
if (nullableAny != null && nullableAny is String?) nullableAny.length
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test7(bar: Any) {
|
||||||
|
val test = bar is String
|
||||||
|
if (test) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
if (bar is String) bar.length
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test8(bar: Any) {
|
||||||
|
val test = bar is String
|
||||||
|
when {
|
||||||
|
test -> bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
}
|
||||||
|
when {
|
||||||
|
bar is String -> bar.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test9(bar: Any) {
|
||||||
|
bar is String && bar.length == 0
|
||||||
|
val test = bar is String
|
||||||
|
test && bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test10(bar: Any) {
|
||||||
|
val test = bar !is String
|
||||||
|
run {
|
||||||
|
if (test) return@run
|
||||||
|
bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
}
|
||||||
|
run {
|
||||||
|
if (bar !is String) return@run
|
||||||
|
bar.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test11(bar: Any, baz: Any) {
|
||||||
|
val test = baz is String && baz === bar
|
||||||
|
val test2 = baz is String
|
||||||
|
val test3 = baz === bar
|
||||||
|
val test4 = test2 && test3
|
||||||
|
|
||||||
|
if (test) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
if (test2 && test3) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
if (baz is String && test3) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
if (test2 && baz === bar) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
if (test4) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
|
||||||
|
if (baz is String && baz === bar) bar.length
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test12(bar: Any) {
|
||||||
|
val test = bar !is String
|
||||||
|
if (!test) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test13(bar: Any) {
|
||||||
|
val test = bar is String
|
||||||
|
if (test == true) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
when (test) {
|
||||||
|
true -> bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
false -> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
val test2: Boolean? = bar is String
|
||||||
|
if (test2 == true) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test14(bar: Any) {
|
||||||
|
val test = (bar as? String) != null
|
||||||
|
if (test) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test15(bar: Any) {
|
||||||
|
val test = bar is String
|
||||||
|
val test2 = test
|
||||||
|
if (test2) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test16(bar: Any) {
|
||||||
|
val x = bar.isString()
|
||||||
|
if (x) bar.<!UNRESOLVED_REFERENCE!>length<!>
|
||||||
|
if (bar.isString()) bar.length
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
fun Any.isString(): Boolean {
|
||||||
|
contract {
|
||||||
|
returns(true) implies (this@isString is String)
|
||||||
|
}
|
||||||
|
return this is String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.isEmpty(): Boolean = length == 0
|
||||||
|
fun test17(a: String?) {
|
||||||
|
val x = a?.length
|
||||||
|
if (x != null) a.length
|
||||||
|
|
||||||
|
val y = a?.isEmpty()
|
||||||
|
if (y == true) a.length
|
||||||
|
}
|
||||||
Generated
+6
@@ -34962,6 +34962,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
runTest("compiler/testData/diagnostics/tests/smartCasts/dataFlowInfoForArguments.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disableDfaBooleanVariables.kt")
|
||||||
|
public void testDisableDfaBooleanVariables() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/smartCasts/disableDfaBooleanVariables.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("doubleLambdaArgument.kt")
|
@TestMetadata("doubleLambdaArgument.kt")
|
||||||
public void testDoubleLambdaArgument() throws Exception {
|
public void testDoubleLambdaArgument() throws Exception {
|
||||||
|
|||||||
@@ -308,6 +308,7 @@ enum class LanguageFeature(
|
|||||||
ForbidInferringTypeVariablesIntoEmptyIntersection(KOTLIN_2_0, kind = BUG_FIX), // KT-51221
|
ForbidInferringTypeVariablesIntoEmptyIntersection(KOTLIN_2_0, kind = BUG_FIX), // KT-51221
|
||||||
ProhibitDefaultArgumentsInExpectActualizedByFakeOverride(KOTLIN_2_0, kind = BUG_FIX), // KT-62036
|
ProhibitDefaultArgumentsInExpectActualizedByFakeOverride(KOTLIN_2_0, kind = BUG_FIX), // KT-62036
|
||||||
DisableCompatibilityModeForNewInference(KOTLIN_2_0, kind = OTHER), // KT-63558 (umbrella), KT-64306, KT-64307, KT-64308
|
DisableCompatibilityModeForNewInference(KOTLIN_2_0, kind = OTHER), // KT-63558 (umbrella), KT-64306, KT-64307, KT-64308
|
||||||
|
DfaBooleanVariables(KOTLIN_2_0), // KT-25747
|
||||||
|
|
||||||
// 2.1
|
// 2.1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user