diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/capturingInInitializer.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/capturingInInitializer.kt new file mode 100644 index 00000000000..e25e57f65ed --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/capturingInInitializer.kt @@ -0,0 +1,37 @@ +// !LANGUAGE: +VariableDeclarationInWhenSubject +// !DIAGNOSTICS: -UNUSED_VARIABLE + +fun getBoolean() = true + +fun testSafeCaptureVarInInitializer() { + var x: Int? = 42 + x!! + x.inc() + + val s = when (val y = run { x = 42; 32 }) { + 0 -> { + x.inc() // TODO fix smart casts for captured variables + "0" + } + else -> "!= 0" + } + + x.inc() // TODO fix smart casts for captured variables +} + + +fun testUnsafeCaptureVarInInitializer() { + var x: Int? = 42 + x!! + x.inc() + + val s = when (val y = run { x = null; 32 }) { + 0 -> { + x.inc() // NB smart cast should be impossible + "0" + } + else -> "!= 0" + } + + x.inc() // NB smart cast should be impossible +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/capturingInInitializer.txt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/capturingInInitializer.txt new file mode 100644 index 00000000000..68282c7c3a8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/capturingInInitializer.txt @@ -0,0 +1,5 @@ +package + +public fun getBoolean(): kotlin.Boolean +public fun testSafeCaptureVarInInitializer(): kotlin.Unit +public fun testUnsafeCaptureVarInInitializer(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/jumpoutInInitializer.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/jumpoutInInitializer.kt new file mode 100644 index 00000000000..3419d07918f --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/jumpoutInInitializer.kt @@ -0,0 +1,43 @@ +// !LANGUAGE: +VariableDeclarationInWhenSubject +// !DIAGNOSTICS: -UNUSED_VARIABLE + + +fun testJumpOutInElvis(x: Int?) { + loop@ while (true) { + val y = when (val z = x ?: break@loop) { + 0 -> "0" + else -> "not 0" + } + + x.inc() + } + + x.inc() +} + +fun testJumpOutInElvisLikeIf(x: Int?) { + loop@ while (true) { + val y = when (val z = if (x == null) break@loop else x) { + 0 -> "0" + else -> "not 0" + } + x.inc() + } + + x.inc() +} + + +fun getBoolean() = true + +fun testJumpOutInIf(x: Int?) { + loop@ while (true) { + val y = when (val z = if (getBoolean()) { x!!; break@loop } else x) { + 0 -> "0" + else -> "not 0" + } + x.inc() + } + + x.inc() // Actually, safe, but it's OK if it's error +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/jumpoutInInitializer.txt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/jumpoutInInitializer.txt new file mode 100644 index 00000000000..10e776cb57d --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/jumpoutInInitializer.txt @@ -0,0 +1,6 @@ +package + +public fun getBoolean(): kotlin.Boolean +public fun testJumpOutInElvis(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun testJumpOutInElvisLikeIf(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun testJumpOutInIf(/*0*/ x: kotlin.Int?): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/noSubjectVariableName.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/noSubjectVariableName.kt new file mode 100644 index 00000000000..82c12f2fa0d --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/noSubjectVariableName.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +VariableDeclarationInWhenSubject +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER + + +fun testNoSubjectVariableName(x: Int?) { + val y = when (val = 42) { + 0 -> "0" + else -> "not 0" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/noSubjectVariableName.txt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/noSubjectVariableName.txt new file mode 100644 index 00000000000..6a45d1bad0a --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/noSubjectVariableName.txt @@ -0,0 +1,3 @@ +package + +public fun testNoSubjectVariableName(/*0*/ x: kotlin.Int?): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt new file mode 100644 index 00000000000..e13cf7c9507 --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: +VariableDeclarationInWhenSubject +// !DIAGNOSTICS: -UNUSED_VARIABLE + +enum class E { FIRST, SECOND } + +fun testSmartcastToEnumInSubjectInitializer(e: E?) { + val x = when (val ne = e!!) { // TODO fix + E.FIRST -> "f" + E.SECOND -> "s" + } +} + + +sealed class Either +class Left : Either() +class Right : Either() + +fun testSmartcastToSealedInSubjectInitializer(x: Any?) { + val y = when (val either = x as Either) { // TODO fix + is Left -> "L" + is Right -> "R" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.txt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.txt new file mode 100644 index 00000000000..e8cf80de574 --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.txt @@ -0,0 +1,46 @@ +package + +public fun testSmartcastToEnumInSubjectInitializer(/*0*/ e: E?): kotlin.Unit +public fun testSmartcastToSealedInSubjectInitializer(/*0*/ x: kotlin.Any?): kotlin.Unit + +public final enum class E : kotlin.Enum { + enum entry FIRST + + enum entry SECOND + + private constructor E() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E + public final /*synthesized*/ fun values(): kotlin.Array +} + +public sealed class Either { + private constructor Either() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Left : Either { + public constructor Left() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Right : Either { + public constructor Right() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 1c4925d4de0..b112cb38390 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -22470,16 +22470,31 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/when/withSubjectVariable"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("capturingInInitializer.kt") + public void testCapturingInInitializer() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/capturingInInitializer.kt"); + } + @TestMetadata("invisibleOutsideOfWhen.kt") public void testInvisibleOutsideOfWhen() throws Exception { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/invisibleOutsideOfWhen.kt"); } + @TestMetadata("jumpoutInInitializer.kt") + public void testJumpoutInInitializer() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/jumpoutInInitializer.kt"); + } + @TestMetadata("nestedWhenWithSubject.kt") public void testNestedWhenWithSubject() throws Exception { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.kt"); } + @TestMetadata("noSubjectVariableName.kt") + public void testNoSubjectVariableName() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/noSubjectVariableName.kt"); + } + @TestMetadata("reassignmentToWhenSubjectVariable.kt") public void testReassignmentToWhenSubjectVariable() throws Exception { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/reassignmentToWhenSubjectVariable.kt"); @@ -22500,6 +22515,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastsOnSubjectVariable.kt"); } + @TestMetadata("smartcastToEnum.kt") + public void testSmartcastToEnum() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt"); + } + @TestMetadata("subjectVariableInIsPattern.kt") public void testSubjectVariableInIsPattern() throws Exception { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/subjectVariableInIsPattern.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index b4e877644b8..9996abea9ba 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -22470,16 +22470,31 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/when/withSubjectVariable"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("capturingInInitializer.kt") + public void testCapturingInInitializer() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/capturingInInitializer.kt"); + } + @TestMetadata("invisibleOutsideOfWhen.kt") public void testInvisibleOutsideOfWhen() throws Exception { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/invisibleOutsideOfWhen.kt"); } + @TestMetadata("jumpoutInInitializer.kt") + public void testJumpoutInInitializer() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/jumpoutInInitializer.kt"); + } + @TestMetadata("nestedWhenWithSubject.kt") public void testNestedWhenWithSubject() throws Exception { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.kt"); } + @TestMetadata("noSubjectVariableName.kt") + public void testNoSubjectVariableName() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/noSubjectVariableName.kt"); + } + @TestMetadata("reassignmentToWhenSubjectVariable.kt") public void testReassignmentToWhenSubjectVariable() throws Exception { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/reassignmentToWhenSubjectVariable.kt"); @@ -22500,6 +22515,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastsOnSubjectVariable.kt"); } + @TestMetadata("smartcastToEnum.kt") + public void testSmartcastToEnum() throws Exception { + runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt"); + } + @TestMetadata("subjectVariableInIsPattern.kt") public void testSubjectVariableInIsPattern() throws Exception { runTest("compiler/testData/diagnostics/tests/when/withSubjectVariable/subjectVariableInIsPattern.kt");