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 dcdae243376..daec6955089 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 @@ -32915,6 +32915,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("flexibleSealedInSubject.kt") + public void testFlexibleSealedInSubject() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.kt"); + } + @Test @TestMetadata("javaSealedClassExhaustiveness.kt") public void testJavaSealedClassExhaustiveness() throws Exception { @@ -35226,6 +35232,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/when/extractingEntireCall.kt"); } + @Test + @TestMetadata("flexibleEnumInSubject.kt") + public void testFlexibleEnumInSubject() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/flexibleEnumInSubject.kt"); + } + @Test @TestMetadata("intersectionExhaustivenessComplex.kt") public void testIntersectionExhaustivenessComplex() throws Exception { 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 88e4c3b4367..94f0d939213 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 @@ -32915,6 +32915,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("flexibleSealedInSubject.kt") + public void testFlexibleSealedInSubject() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.kt"); + } + @Test @TestMetadata("javaSealedClassExhaustiveness.kt") public void testJavaSealedClassExhaustiveness() throws Exception { @@ -35226,6 +35232,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/when/extractingEntireCall.kt"); } + @Test + @TestMetadata("flexibleEnumInSubject.kt") + public void testFlexibleEnumInSubject() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/flexibleEnumInSubject.kt"); + } + @Test @TestMetadata("intersectionExhaustivenessComplex.kt") public void testIntersectionExhaustivenessComplex() throws Exception { 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 6e940773a2a..06ac6458cb7 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 @@ -33011,6 +33011,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("flexibleSealedInSubject.kt") + public void testFlexibleSealedInSubject() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.kt"); + } + @Test @TestMetadata("javaSealedClassExhaustiveness.kt") public void testJavaSealedClassExhaustiveness() throws Exception { @@ -35322,6 +35328,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/when/extractingEntireCall.kt"); } + @Test + @TestMetadata("flexibleEnumInSubject.kt") + public void testFlexibleEnumInSubject() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/flexibleEnumInSubject.kt"); + } + @Test @TestMetadata("intersectionExhaustivenessComplex.kt") public void testIntersectionExhaustivenessComplex() throws Exception { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt index fe073021f9a..26781678def 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.isBooleanOrNullableBoolean +import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible import org.jetbrains.kotlin.fir.types.toRegularClassSymbol object FirExhaustiveWhenChecker : FirWhenExpressionChecker() { @@ -45,7 +46,7 @@ object FirExhaustiveWhenChecker : FirWhenExpressionChecker() { reporter.reportOn(source, FirErrors.NO_ELSE_IN_WHEN, whenExpression.missingCases, context) } } else { - val subjectType = whenExpression.subject?.typeRef?.coneType ?: return + val subjectType = whenExpression.subject?.typeRef?.coneType?.lowerBoundIfFlexible() ?: return val subjectClassSymbol = subjectType.fullyExpandedType(context.session).toRegularClassSymbol(context.session) ?: return val kind = when { subjectClassSymbol.modality == Modality.SEALED -> AlgebraicTypeKind.Sealed diff --git a/compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.fir.kt b/compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.fir.kt new file mode 100644 index 00000000000..0abc4437171 --- /dev/null +++ b/compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.fir.kt @@ -0,0 +1,59 @@ +// ISSUE: KT-56942 +// FILE: Base.java +public sealed class Base permits A, B { + public static Base provide() { return new A(); } +} + +// FILE: A.java +public final class A extends Base {} + +// FILE: B.java +public final class B extends Base {} + +// FILE: main.kt + +fun test_0(base: Base) { + when (base) { + + } + + when (base) { + is A -> {} + is B -> {} + } + + when (base) { + is A -> {} + is B -> {} + null -> {} + } + + when (base) { + is A -> {} + is B -> {} + else -> {} + } +} + +fun test_1() { + when (Base.provide()) { + + } + + when (Base.provide()) { + is A -> {} + is B -> {} + } + + when (Base.provide()) { + is A -> {} + is B -> {} + null -> {} + } + + when (Base.provide()) { + is A -> {} + is B -> {} + else -> {} + } +} diff --git a/compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.kt b/compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.kt new file mode 100644 index 00000000000..168e5e74a65 --- /dev/null +++ b/compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.kt @@ -0,0 +1,59 @@ +// ISSUE: KT-56942 +// FILE: Base.java +public sealed class Base permits A, B { + public static Base provide() { return new A(); } +} + +// FILE: A.java +public final class A extends Base {} + +// FILE: B.java +public final class B extends Base {} + +// FILE: main.kt + +fun test_0(base: Base) { + when (base) { + + } + + when (base) { + is A -> {} + is B -> {} + } + + when (base) { + is A -> {} + is B -> {} + null -> {} + } + + when (base) { + is A -> {} + is B -> {} + else -> {} + } +} + +fun test_1() { + when (Base.provide()) { + + } + + when (Base.provide()) { + is A -> {} + is B -> {} + } + + when (Base.provide()) { + is A -> {} + is B -> {} + null -> {} + } + + when (Base.provide()) { + is A -> {} + is B -> {} + else -> {} + } +} diff --git a/compiler/testData/diagnostics/tests/when/flexibleEnumInSubject.kt b/compiler/testData/diagnostics/tests/when/flexibleEnumInSubject.kt new file mode 100644 index 00000000000..114a08ce220 --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/flexibleEnumInSubject.kt @@ -0,0 +1,51 @@ +// FIR_IDENTICAL +// ISSUE: KT-56942 +// FILE: EnumJava.java +public enum EnumJava { + JAVA_ONE, JAVA_TWO; + + public static EnumJava provide() { return EnumJava.JAVA_ONE; } +} + +// FILE: EnumProviderJava.java +public class EnumProviderJava { + public static EnumJava provide() { return EnumJava.JAVA_ONE; } +} + + +// FILE: main.kt +enum class EnumKotlin { + KOTLIN_ONE, KOTLIN_TWO; + + companion object { + fun provide(): EnumKotlin = EnumKotlin.KOTLIN_ONE + } +} + +fun test_1(ejp: EnumJava, ekp: EnumKotlin) { + when (ejp) { + EnumJava.JAVA_ONE -> {} + } + + when (ekp) { + EnumKotlin.KOTLIN_ONE -> {} + } + + when (EnumJava.provide()) { + EnumJava.JAVA_ONE -> {} + } + + when (EnumKotlin.provide()) { + EnumKotlin.KOTLIN_ONE -> {} + } +} + +fun test_2(ejp: EnumJava, ekp: EnumKotlin) { + when (ejp) {} + + when (ekp) {} + + when (EnumProviderJava.provide()) {} + + when (EnumKotlin.provide()) {} +} 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 ef3421d88b2..639b4b37b9a 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 @@ -33011,6 +33011,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true); } + @Test + @TestMetadata("flexibleSealedInSubject.kt") + public void testFlexibleSealedInSubject() throws Exception { + runTest("compiler/testData/diagnostics/tests/testsWithJava17/sealedClasses/flexibleSealedInSubject.kt"); + } + @Test @TestMetadata("javaSealedClassExhaustiveness.kt") public void testJavaSealedClassExhaustiveness() throws Exception { @@ -35322,6 +35328,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/when/extractingEntireCall.kt"); } + @Test + @TestMetadata("flexibleEnumInSubject.kt") + public void testFlexibleEnumInSubject() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/flexibleEnumInSubject.kt"); + } + @Test @TestMetadata("intersectionExhaustivenessComplex.kt") public void testIntersectionExhaustivenessComplex() throws Exception {