diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index cc3550102f0af..11577f6bc0634 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -6313,6 +6313,12 @@ public void testKt4310() throws Exception { runTest("compiler/testData/diagnostics/tests/controlStructures/kt4310.kt"); } + @Test + @TestMetadata("kt51711.kt") + public void testKt51711() throws Exception { + runTest("compiler/testData/diagnostics/tests/controlStructures/kt51711.kt"); + } + @Test @TestMetadata("kt657.kt") public void testKt657() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index f4b0f6f081c79..be011fe532b50 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -6313,6 +6313,12 @@ public void testKt4310() throws Exception { runTest("compiler/testData/diagnostics/tests/controlStructures/kt4310.kt"); } + @Test + @TestMetadata("kt51711.kt") + public void testKt51711() throws Exception { + runTest("compiler/testData/diagnostics/tests/controlStructures/kt51711.kt"); + } + @Test @TestMetadata("kt657.kt") public void testKt657() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index b9e7498bc586b..aedb8f86a8d5c 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -6313,6 +6313,12 @@ public void testKt4310() throws Exception { runTest("compiler/testData/diagnostics/tests/controlStructures/kt4310.kt"); } + @Test + @TestMetadata("kt51711.kt") + public void testKt51711() throws Exception { + runTest("compiler/testData/diagnostics/tests/controlStructures/kt51711.kt"); + } + @Test @TestMetadata("kt657.kt") public void testKt657() throws Exception { diff --git a/compiler/frontend/cfg/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProviderImpl.kt b/compiler/frontend/cfg/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProviderImpl.kt index 1429c4ff3c141..035cbc67f1317 100644 --- a/compiler/frontend/cfg/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProviderImpl.kt +++ b/compiler/frontend/cfg/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProviderImpl.kt @@ -955,20 +955,23 @@ class ControlFlowInformationProviderImpl private constructor( for (element in instruction.owner.getValueElements(value)) { if (element !is KtIfExpression) continue - if (element.isUsedAsExpression(trace.bindingContext)) { - val thenExpression = element.then - val elseExpression = element.`else` + val thenExpression = element.then + val elseExpression = element.`else` + val isEhxaustive = thenExpression != null && elseExpression != null - if (thenExpression == null || elseExpression == null) { + if (element.isUsedAsExpression(trace.bindingContext)) { + if (!isEhxaustive) { trace.report(INVALID_IF_AS_EXPRESSION.on(element.ifKeyword)) } else { checkImplicitCastOnConditionalExpression(element) } } else if (!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonExhaustiveIfInRhsOfElvis)) { - val parent = element.deparenthesizedParent - if (parent is KtBinaryExpression) { - if (parent.operationToken === KtTokens.ELVIS) { - trace.report(INVALID_IF_AS_EXPRESSION_WARNING.on(element.getIfKeyword())) + if (!isEhxaustive) { + val parent = element.deparenthesizedParent + if (parent is KtBinaryExpression) { + if (parent.operationToken === KtTokens.ELVIS) { + trace.report(INVALID_IF_AS_EXPRESSION_WARNING.on(element.getIfKeyword())) + } } } } @@ -1067,6 +1070,7 @@ class ControlFlowInformationProviderImpl private constructor( if ( !usedAsExpression && missingCases.isNotEmpty() && + elseEntry == null && !languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonExhaustiveIfInRhsOfElvis) ) { val parent = element.deparenthesizedParent diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt51711.kt b/compiler/testData/diagnostics/tests/controlStructures/kt51711.kt new file mode 100644 index 0000000000000..5c031d7d0a088 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/kt51711.kt @@ -0,0 +1,22 @@ +// FIR_IDENTICAL +// LANGUAGE: -ProhibitNonExhaustiveIfInRhsOfElvis +// ISSUE: KT-51711 +// WITH_STDLIB + +private fun fake(a: String?) {} + +fun test_1(x: String?, y: String?) { + while (true) { + x ?: if (y == null) break else fake(y) + } +} + + +fun test_2(x: String?, y: String?) { + while (true) { + x ?: when { + true -> break + else -> y?.filter { it.isLowerCase() } + } + } +} diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt51711.txt b/compiler/testData/diagnostics/tests/controlStructures/kt51711.txt new file mode 100644 index 0000000000000..49f468e5c5018 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/kt51711.txt @@ -0,0 +1,5 @@ +package + +private fun fake(/*0*/ a: kotlin.String?): kotlin.Unit +public fun test_1(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Unit +public fun test_2(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Unit diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 73f431d4d2f76..fe97a90d4c90d 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -6319,6 +6319,12 @@ public void testKt4310() throws Exception { runTest("compiler/testData/diagnostics/tests/controlStructures/kt4310.kt"); } + @Test + @TestMetadata("kt51711.kt") + public void testKt51711() throws Exception { + runTest("compiler/testData/diagnostics/tests/controlStructures/kt51711.kt"); + } + @Test @TestMetadata("kt657.kt") public void testKt657() throws Exception {