From 9748df73ffdbc8672f1ba17b9fdde7d89f1e3db2 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Mon, 23 Sep 2024 10:56:30 +0200 Subject: [PATCH] [FIR] Prohibit Nothing as catch parameter type #KT-8322 Fixed --- ...agnosticCompilerTestFE10TestdataTestGenerated.java | 6 ++++++ ...edDiagnosticCompilerFE10TestDataTestGenerated.java | 6 ++++++ ...rLightTreeOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ ...nosticsWithLatestLanguageVersionTestGenerated.java | 6 ++++++ .../FirPsiOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ .../checkers/expression/FirCatchParameterChecker.kt | 9 ++++++++- .../tests/controlStructures/catchOfTypeNothing.fir.kt | 11 +++++++++++ .../tests/controlStructures/catchOfTypeNothing.kt | 11 +++++++++++ .../kotlin/test/runners/DiagnosticTestGenerated.java | 6 ++++++ .../kotlin/config/LanguageVersionSettings.kt | 1 + 10 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.fir.kt create mode 100644 compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 78d8599061c31..8fa28540c48a3 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -8582,6 +8582,12 @@ public void testCatchInnerClassesOfGenerics_deprecation() { runTest("compiler/testData/diagnostics/tests/controlStructures/catchInnerClassesOfGenerics_deprecation.kt"); } + @Test + @TestMetadata("catchOfTypeNothing.kt") + public void testCatchOfTypeNothing() { + runTest("compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt"); + } + @Test @TestMetadata("catchWithDefault.kt") public void testCatchWithDefault() { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 7ed1490e25941..c5e8d347f957c 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -8582,6 +8582,12 @@ public void testCatchInnerClassesOfGenerics_deprecation() { runTest("compiler/testData/diagnostics/tests/controlStructures/catchInnerClassesOfGenerics_deprecation.kt"); } + @Test + @TestMetadata("catchOfTypeNothing.kt") + public void testCatchOfTypeNothing() { + runTest("compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt"); + } + @Test @TestMetadata("catchWithDefault.kt") public void testCatchWithDefault() { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 6de61fb6b1236..c14e82e8df691 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -8576,6 +8576,12 @@ public void testCatchInnerClassesOfGenerics_deprecation() { runTest("compiler/testData/diagnostics/tests/controlStructures/catchInnerClassesOfGenerics_deprecation.kt"); } + @Test + @TestMetadata("catchOfTypeNothing.kt") + public void testCatchOfTypeNothing() { + runTest("compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt"); + } + @Test @TestMetadata("catchWithDefault.kt") public void testCatchWithDefault() { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsWithLatestLanguageVersionTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsWithLatestLanguageVersionTestGenerated.java index 40fb69f330ba7..df818f00ab2ce 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsWithLatestLanguageVersionTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsWithLatestLanguageVersionTestGenerated.java @@ -8576,6 +8576,12 @@ public void testCatchInnerClassesOfGenerics_deprecation() { runTest("compiler/testData/diagnostics/tests/controlStructures/catchInnerClassesOfGenerics_deprecation.kt"); } + @Test + @TestMetadata("catchOfTypeNothing.kt") + public void testCatchOfTypeNothing() { + runTest("compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt"); + } + @Test @TestMetadata("catchWithDefault.kt") public void testCatchWithDefault() { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index e567fc8c0af3d..17c49c127c2b9 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -8582,6 +8582,12 @@ public void testCatchInnerClassesOfGenerics_deprecation() { runTest("compiler/testData/diagnostics/tests/controlStructures/catchInnerClassesOfGenerics_deprecation.kt"); } + @Test + @TestMetadata("catchOfTypeNothing.kt") + public void testCatchOfTypeNothing() { + runTest("compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt"); + } + @Test @TestMetadata("catchWithDefault.kt") public void testCatchWithDefault() { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt index 5b9fe6f8cb2e1..7e3a72fa938cf 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCatchParameterChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind @@ -14,8 +15,10 @@ import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeOfThrowable import org.jetbrains.kotlin.fir.analysis.checkers.valOrVarKeyword import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.expressions.FirTryExpression +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeTypeParameterType import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.isNothing import org.jetbrains.kotlin.fir.types.isTypeMismatchDueToNullability import org.jetbrains.kotlin.fir.types.typeContext @@ -45,7 +48,7 @@ object FirCatchParameterChecker : FirTryExpressionChecker(MppCheckerKind.Common) } val session = context.session - if (!coneType.isSubtypeOfThrowable(session)) { + if (!coneType.isSubtypeOfThrowable(session) || isProhibitedNothing(context, coneType)) { reporter.reportOn( source, FirErrors.THROWABLE_TYPE_MISMATCH, @@ -59,4 +62,8 @@ object FirCatchParameterChecker : FirTryExpressionChecker(MppCheckerKind.Common) } } } + + private fun isProhibitedNothing(context: CheckerContext, coneType: ConeKotlinType): Boolean { + return context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNothingAsCatchParameter) && coneType.isNothing + } } diff --git a/compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.fir.kt new file mode 100644 index 0000000000000..6ab6e11affb3a --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.fir.kt @@ -0,0 +1,11 @@ +fun foo() { + try { + throw Exception() + } catch (x: Nothing) { + } + + try { + throw Exception() + } catch (x: Nothing?) { + } +} diff --git a/compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt b/compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt new file mode 100644 index 0000000000000..804c8838d7a95 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt @@ -0,0 +1,11 @@ +fun foo() { + try { + throw Exception() + } catch (x: Nothing) { + } + + try { + throw Exception() + } catch (x: Nothing?) { + } +} \ No newline at end of file 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 1c657663dd5cc..a1d57c801d155 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 @@ -8582,6 +8582,12 @@ public void testCatchInnerClassesOfGenerics_deprecation() { runTest("compiler/testData/diagnostics/tests/controlStructures/catchInnerClassesOfGenerics_deprecation.kt"); } + @Test + @TestMetadata("catchOfTypeNothing.kt") + public void testCatchOfTypeNothing() { + runTest("compiler/testData/diagnostics/tests/controlStructures/catchOfTypeNothing.kt"); + } + @Test @TestMetadata("catchWithDefault.kt") public void testCatchWithDefault() { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index b962bb9e65828..48056ce08c553 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -337,6 +337,7 @@ enum class LanguageFeature( AllowSuperCallToJavaInterface(KOTLIN_2_1, kind = OTHER), // KT-69729 ProhibitJavaClassInheritingPrivateKotlinClass(KOTLIN_2_1, kind = BUG_FIX), // KT-66328 ProhibitReturningIncorrectNullabilityValuesFromSamConstructorLambdaOfJdkInterfaces(KOTLIN_2_1, kind = BUG_FIX), // KT-57014 + ProhibitNothingAsCatchParameter(KOTLIN_2_1, kind = BUG_FIX), // KT-8322 // It's not a fully blown LF, but mostly a way to manage potential unexpected semantic changes // See the single usage at org.jetbrains.kotlin.fir.types.ConeTypeApproximator.fastPathSkipApproximation