[FIR] Implement checker for exhaustive when's in expression position

This commit is contained in:
Dmitriy Novozhilov
2021-02-04 15:41:57 +03:00
parent 3f715e671d
commit 8dd9d98129
103 changed files with 919 additions and 617 deletions
@@ -72,7 +72,7 @@ fun main1() {
1."sdf"
1.{}
1.if (true) {}
1.<!INVALID_IF_AS_EXPRESSION!>if<!> (true) {}
}
fun test() {
@@ -70,7 +70,7 @@ fun blockReturnValueTypeMatch1() : Int {
return if (1 > 2) 1.0 else 2.0
}
fun blockReturnValueTypeMatch2() : Int {
return if (1 > 2) 1
return <!INVALID_IF_AS_EXPRESSION!>if<!> (1 > 2) 1
}
fun blockReturnValueTypeMatch3() : Int {
return if (1 > 2) else 1
@@ -106,7 +106,7 @@ fun blockReturnValueTypeMatch9() : Int {
1.0
}
fun blockReturnValueTypeMatch10() : Int {
return if (1 > 2)
return <!INVALID_IF_AS_EXPRESSION!>if<!> (1 > 2)
1
}
fun blockReturnValueTypeMatch11() : Int {
@@ -29,7 +29,7 @@ fun foo(d: Direction) = when(d) { //no 'else' should be requested
Direction.EAST -> 4
}
fun foo1(d: Direction) = when(d) {
fun foo1(d: Direction) = <!NO_ELSE_IN_WHEN!>when<!>(d) {
Direction.NORTH -> 1
Direction.SOUTH -> 2
Direction.WEST -> 3
@@ -41,7 +41,7 @@ fun bar(c: Color) = when (c) {
Color.BLUE -> 3
}
fun bar1(c: Color) = when (c) {
fun bar1(c: Color) = <!NO_ELSE_IN_WHEN!>when<!> (c) {
Color.RED -> 1
Color.GREEN -> 2
}
}
@@ -1,16 +0,0 @@
fun foo(x: Unit) = x
fun test() {
if (false);
if (true);
val x = if (false);
foo(x)
val y: Unit = if (false);
foo(y)
foo({if (1==1);}())
return if (true);
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun foo(x: Unit) = x
fun test() {
@@ -11,7 +11,7 @@ fun testMixedIfAndWhen() =
else 1
true -> if (true) 42
else println()
else -> if (true) println()
else -> <!INVALID_IF_AS_EXPRESSION!>if<!> (true) println()
}
else println()
@@ -28,4 +28,4 @@ fun testWrappedExpressions() =
}
else {
(((((42)) + 1)))
}
}
@@ -11,21 +11,21 @@ val mlist = MList()
fun work() {}
val xx1 = if (true) 42
val xx2: Unit = if (true) 42
val xx3 = idAny(if (true) 42)
val xx4 = id(if (true) 42)
val xx5 = idUnit(if (true) 42)
val xx6 = null ?: if (true) 42
val xx7 = "" + if (true) 42
val xx1 = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
val xx2: Unit = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
val xx3 = idAny(<!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42)
val xx4 = id(<!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42)
val xx5 = idUnit(<!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42)
val xx6 = null ?: <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
val xx7 = "" + <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
val wxx1 = when { true -> 42 }
val wxx2: Unit = when { true -> 42 }
val wxx3 = idAny(when { true -> 42 })
val wxx4 = id(when { true -> 42 })
val wxx5 = idUnit(when { true -> 42 })
val wxx6 = null ?: when { true -> 42 }
val wxx7 = "" + when { true -> 42 }
val wxx1 = <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
val wxx2: Unit = <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
val wxx3 = idAny(<!NO_ELSE_IN_WHEN!>when<!> { true -> 42 })
val wxx4 = id(<!NO_ELSE_IN_WHEN!>when<!> { true -> 42 })
val wxx5 = idUnit(<!NO_ELSE_IN_WHEN!>when<!> { true -> 42 })
val wxx6 = null ?: <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
val wxx7 = "" + <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
val fn1 = { if (true) 42 }
val fn2 = { if (true) mlist.add() }
@@ -41,24 +41,24 @@ val ufn4: () -> Unit = { when { true -> 42 } }
val ufn5: () -> Unit = { when { true -> mlist.add() } }
val ufn6: () -> Unit = { when { true -> work() } }
fun f1() = if (true) work()
fun f2() = if (true) mlist.add()
fun f3() = if (true) 42
fun f4(): Unit = if (true) work()
fun f5(): Unit = if (true) mlist.add()
fun f6(): Unit = if (true) 42
fun g1() = when { true -> work() }
fun g2() = when { true -> mlist.add() }
fun g3() = when { true -> 42 }
fun g4(): Unit = when { true -> work() }
fun g5(): Unit = when { true -> mlist.add() }
fun g6(): Unit = when { true -> 42 }
fun f1() = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) work()
fun f2() = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) mlist.add()
fun f3() = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
fun f4(): Unit = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) work()
fun f5(): Unit = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) mlist.add()
fun f6(): Unit = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
fun g1() = <!NO_ELSE_IN_WHEN!>when<!> { true -> work() }
fun g2() = <!NO_ELSE_IN_WHEN!>when<!> { true -> mlist.add() }
fun g3() = <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
fun g4(): Unit = <!NO_ELSE_IN_WHEN!>when<!> { true -> work() }
fun g5(): Unit = <!NO_ELSE_IN_WHEN!>when<!> { true -> mlist.add() }
fun g6(): Unit = <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
fun foo1(x: String?) {
"" + if (true) 42
"" + <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
w@while (true) {
x ?: if (true) break
x ?: when { true -> break@w }
x ?: <!INVALID_IF_AS_EXPRESSION!>if<!> (true) break
x ?: <!NO_ELSE_IN_WHEN!>when<!> { true -> break@w }
}
}
@@ -4,7 +4,7 @@
fun example() {
val a = if (true) true else false
val b = if (true) else false
val c = if (true) true
val c = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) true
val d = if (true) true else;
val e = if (true) {} else false
val f = if (true) true else {}
@@ -27,7 +27,7 @@ fun example() {
}()
fun t(): Boolean {
return if (true) true
return <!INVALID_IF_AS_EXPRESSION!>if<!> (true) true
}
return if (true) true else {}
@@ -99,10 +99,10 @@ fun testImplicitCoercion() {
else -> z--
}
var iff = if (true) {
var iff = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) {
z = 34
}
val g = if (true) 4
val g = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 4
val h = if (false) 4 else {}
<!INAPPLICABLE_CANDIDATE!>bar<!>(if (true) {
@@ -25,7 +25,7 @@ fun t1(x: Int) = when(x) {
else -> 1
}
fun t5(x: Int) = when (x) {
fun t5(x: Int) = <!NO_ELSE_IN_WHEN!>when<!> (x) {
is Int -> 1
2 -> 2
}
@@ -18,7 +18,7 @@ fun f3(s: Number?) {
}
fun f4(s: Int?) {
var u = if (s!! == 42);
if (u == Unit) u = if (s == 239);
var u = <!INVALID_IF_AS_EXPRESSION!>if<!> (s!! == 42);
if (u == Unit) u = <!INVALID_IF_AS_EXPRESSION!>if<!> (s == 239);
return u
}
}
@@ -142,7 +142,7 @@ fun getStringLength(obj : Any) : Char? {
}
fun toInt(i: Int?): Int = if (i != null) i else 0
fun illegalWhenBody(a: Any): Int = when(a) {
fun illegalWhenBody(a: Any): Int = <!NO_ELSE_IN_WHEN!>when<!>(a) {
is Int -> a
is String -> a
}
@@ -13,11 +13,11 @@ fun test(x: Stmt): String =
}
fun test2(x: Stmt): String =
when (x) {
<!NO_ELSE_IN_WHEN!>when<!> (x) {
is Expr -> "expr"
}
fun test3(x: Expr): String =
when (x) {
<!NO_ELSE_IN_WHEN!>when<!> (x) {
is Stmt -> "stmt"
}
}
@@ -15,7 +15,7 @@ sealed class Base {
// No else required
}
fun bar() = when (this) {
fun bar() = <!NO_ELSE_IN_WHEN!>when<!> (this) {
is A -> 1
is B.B1 -> 2
}
@@ -31,4 +31,4 @@ sealed class Base {
A.A1 -> 2
is A.A2 -> 3
}
}
}
@@ -1,24 +0,0 @@
sealed class A
sealed class B : A()
class C : B()
class D : B()
fun test(a: A): Any {
return when (a) {
is C -> ""
is D -> ""
}
}
fun test2(a: A): Any {
return when (a) {
is B -> ""
}
}
fun test3(a: A): Any {
return when (a) {
is D -> ""
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
sealed class A
sealed class B : A()
@@ -1,47 +0,0 @@
sealed class Sealed() {
object First: Sealed()
open class NonFirst: Sealed() {
class NonSecond: NonFirst() {
object Third: Sealed()
class NonThird: Sealed() {
object Fourth: NonFirst()
class Fifth: Sealed()
}
}
object Second: Sealed()
}
}
fun foo(s: Sealed) = when(s) {
Sealed.First -> 1
is Sealed.NonFirst -> 2
Sealed.NonFirst.Second -> 4
Sealed.NonFirst.NonSecond.Third -> 6
is Sealed.NonFirst.NonSecond.NonThird -> 8
is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10
// no else required
}
fun fooWithElse(s: Sealed) = when(s) {
Sealed.First -> 1
Sealed.NonFirst.NonSecond.Third -> 6
is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10
else -> 0
}
fun fooWithoutElse(s: Sealed) = when(s) {
Sealed.First -> 1
is Sealed.NonFirst -> 2
Sealed.NonFirst.NonSecond.Third -> 6
is Sealed.NonFirst.NonSecond.NonThird -> 8
is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10
}
fun barWithoutElse(s: Sealed) = when(s) {
Sealed.First -> 1
is Sealed.NonFirst -> 2
Sealed.NonFirst.Second -> 4
is Sealed.NonFirst.NonSecond.NonThird -> 8
is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
sealed class Sealed() {
object First: Sealed()
open class NonFirst: Sealed() {
@@ -1,64 +0,0 @@
// ISSUE: KT-13495
// !DIAGNOSTICS: -UNUSED_VARIABLE
// !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage
// FILE: Base.kt
sealed class Base {
class A : Base()
}
// FILE: B.kt
class B : Base()
// FILE: Container.kt
class Containter {
class C : Base()
inner class D : Base()
}
// FILE: main.kt
fun test_OK(base: Base) {
val x = when (base) {
is Base.A -> 1
is B -> 2
is Containter.C -> 3
is Containter.D -> 4
}
}
fun test_error_1(base: Base) {
val x = when (base) {
is B -> 2
is Containter.C -> 3
is Containter.D -> 4
}
}
fun test_error_2(base: Base) {
val x = when (base) {
is Base.A -> 1
is Containter.C -> 3
is Containter.D -> 4
}
}
fun test_error_3(base: Base) {
val x = when (base) {
is Base.A -> 1
is B -> 2
is Containter.D -> 4
}
}
fun test_error_4(base: Base) {
val x = when (base) {
is Base.A -> 1
is B -> 2
is Containter.C -> 3
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ISSUE: KT-13495
// !DIAGNOSTICS: -UNUSED_VARIABLE
// !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage
@@ -1,14 +0,0 @@
sealed class Sealed(val x: Int) {
object First: Sealed(12)
open class NonFirst(x: Int, val y: Int): Sealed(x) {
object Second: NonFirst(34, 2)
object Third: NonFirst(56, 3)
}
}
fun foo(s: Sealed): Int {
return when(s) {
is Sealed.NonFirst -> 0
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
sealed class Sealed(val x: Int) {
object First: Sealed(12)
open class NonFirst(x: Int, val y: Int): Sealed(x) {
@@ -1,14 +0,0 @@
sealed class Sealed(val x: Int) {
object First: Sealed(12)
open class NonFirst(x: Int, val y: Int): Sealed(x) {
object Second: NonFirst(34, 2)
object Third: NonFirst(56, 3)
}
}
fun foo(s: Sealed): Int {
return when(s) {
!is Sealed.NonFirst -> 1
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
sealed class Sealed(val x: Int) {
object First: Sealed(12)
open class NonFirst(x: Int, val y: Int): Sealed(x) {
@@ -1,22 +0,0 @@
sealed class Sealed(val x: Int) {
interface ITuple {
val x: Int
val y: Int
}
class Tuple(override val x: Int, override val y: Int): ITuple
object First: Sealed(12)
open class NonFirst(tuple: Tuple): Sealed(tuple.x), ITuple {
override val y: Int = tuple.y
object Second: NonFirst(Tuple(34, 2))
class Third: NonFirst(Tuple(56, 3))
}
}
fun foo(s: Sealed): Int {
return when(s) {
is Sealed.First -> 1
!is Sealed.ITuple -> 0
// else required
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
sealed class Sealed(val x: Int) {
interface ITuple {
val x: Int
@@ -7,7 +7,7 @@ sealed class Sealed {
}
fun foo(s: Sealed): Int {
return when(s) {
return <!NO_ELSE_IN_WHEN!>when<!>(s) {
is Sealed.First -> 1
!is Any -> 0
}
@@ -9,7 +9,7 @@ sealed class Tree {
is Node -> this.left.max()
}
fun maxIsClass(): Int = when(this) {
fun maxIsClass(): Int = <!NO_ELSE_IN_WHEN!>when<!>(this) {
Empty -> -1
Leaf -> 0
is Node -> this.left.max()
@@ -20,4 +20,4 @@ sealed class Tree {
is Node -> this.left.max()
else -> -1
}
}
}
@@ -1,11 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION
sealed class Sealed {
}
fun foo(s: Sealed): Int {
return when(s) {
// We do not return anything, so else branch must be here
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION
sealed class Sealed {
@@ -10,7 +10,7 @@ object CC : C()
fun foo(a: A) {
if (a is B) {
if (a is C) {
val t = when (a) {
val t = <!NO_ELSE_IN_WHEN!>when<!> (a) {
is CC -> "CC"
}
}
@@ -20,9 +20,9 @@ fun foo(a: A) {
fun foo2(a: A) {
if (a is C) {
if (a is B) {
val t = when (a) {
val t = <!NO_ELSE_IN_WHEN!>when<!> (a) {
is CC -> "CC"
}
}
}
}
}
@@ -0,0 +1,9 @@
public fun foo(x: String?, y: String?): Int {
while (true) {
x ?: <!INVALID_IF_AS_EXPRESSION!>if<!> (y == null) break
// y is nullable if x != null
y<!UNSAFE_CALL!>.<!>length
}
// y is null because of the break
return y<!UNSAFE_CALL!>.<!>length
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
public fun foo(x: String?, y: String?): Int {
while (true) {
x ?: if (y == null) break
@@ -7,4 +6,4 @@ public fun foo(x: String?, y: String?): Int {
}
// y is null because of the break
return y<!UNSAFE_CALL!>.<!>length
}
}
@@ -1,5 +0,0 @@
fun foo() {}
val x: Unit? = when ("A") {
"B" -> foo()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun foo() {}
val x: Unit? = <!NO_ELSE_IN_WHEN!>when<!> ("A") {
@@ -12,7 +12,7 @@
enum class E { A, B }
fun test(e: E?) = when (e) {
fun test(e: E?) = <!NO_ELSE_IN_WHEN!>when<!> (e) {
E.A -> 1
E.B -> 2
}
@@ -1,18 +1,18 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE)
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* SPEC VERSION: 0.1-313
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 3
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 10
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 4
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 5
*/
// See also: KT-3743
fun foo(arg: Boolean?): String {
// Must be NOT exhaustive
return when(arg) {
true -> "truth"
false -> "falsehood"
fun foo(arg: Boolean): String {
// Must be exhaustive
return <!NO_ELSE_IN_WHEN!>when<!>(arg) {
2 == 2 -> "truth"
2 == 1 -> "falsehood"
}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -12,7 +12,7 @@ enum class MyEnum {
}
fun foo(x: MyEnum): Int {
return when (x) {
return <!NO_ELSE_IN_WHEN!>when<!> (x) {
is <!UNRESOLVED_REFERENCE!>MyEnum.A<!> -> 1
is <!UNRESOLVED_REFERENCE!>MyEnum.B<!> -> 2
is <!UNRESOLVED_REFERENCE!>MyEnum.C<!> -> 3
@@ -13,7 +13,7 @@ enum class MyEnum {
}
fun foo(x: MyEnum): Int {
return when (x) {
return <!NO_ELSE_IN_WHEN!>when<!> (x) {
MyEnum.A -> 1
is <!UNRESOLVED_REFERENCE!>MyEnum.B<!> -> 2
is <!UNRESOLVED_REFERENCE!>MyEnum.C<!> -> 3
@@ -1,16 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 9 -> sentence 2
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
*/
fun foo(x: Int) {
val y: Unit = when (x) {
2 -> {}
3 -> {}
}
return y
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,15 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 9 -> sentence 2
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
*/
fun foo(x: Int): Any {
val v = when (x) {
2 -> 0
}
return v
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,14 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 9 -> sentence 2
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
*/
fun foo(x: Int): Any {
return when (x) {
2 -> 0
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,16 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 9 -> sentence 2
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
*/
fun foo(x: Int) {
return when (x) {
2 -> {}
3 -> {}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE)
*
@@ -1,29 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 9
*/
// See KT-6399: exhaustive whens on platform enums
// FILE: J.java
public enum J {
A, B;
public static J create() {
return J.A;
}
}
// FILE: K.kt
fun foo(): Int {
// When is not-exhaustive
return when (J.create()) {
J.A -> 1
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -13,7 +13,7 @@
enum class X { A, B }
fun foo(arg: X?): Int {
if (arg != null) {
return when (arg) {
return <!NO_ELSE_IN_WHEN!>when<!> (arg) {
X.B -> 2
}
}
@@ -1,32 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 6 -> sentence 1
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 6
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 7
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 8
*/
sealed class A {
class B: A() {
class C: A()
}
}
class D: A()
fun test(a: A) {
val nonExhaustive = when (a) {
is A.B -> "B"
is A.B.C -> "C"
}
val exhaustive = when (a) {
is A.B -> "B"
is A.B.C -> "C"
is D -> "D"
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
+1 -1
View File
@@ -27,7 +27,7 @@ fun foo(): Int {
fun bar(): Int {
val a = "a"
if (a.length > 0) {
return when (a) {
return <!NO_ELSE_IN_WHEN!>when<!> (a) {
"a" -> 1
}
}
@@ -38,4 +38,4 @@ fun test4() {
2 -> bar(x, y)
}
}
}
}
@@ -1,18 +0,0 @@
// !LANGUAGE: +VariableDeclarationInWhenSubject
// !DIAGNOSTICS: -UNUSED_VARIABLE
enum class E { FIRST, SECOND }
fun testSmartcastToEnumInSubjectInitializer1(e: E?) {
val x1 = when (val ne = e!!) {
E.FIRST -> "f"
E.SECOND -> "s"
}
}
fun testSmartcastToEnumInSubjectInitializer2(e: E?) {
val x2 = when (val ne: Any = e!!) { // NB explicit type annotation
E.FIRST -> "f"
E.SECOND -> "s"
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +VariableDeclarationInWhenSubject
// !DIAGNOSTICS: -UNUSED_VARIABLE
@@ -1,20 +0,0 @@
// !LANGUAGE: +VariableDeclarationInWhenSubject
// !DIAGNOSTICS: -UNUSED_VARIABLE
sealed class Either
class Left : Either()
class Right : Either()
fun testSmartcastToSealedInSubjectInitializer1(x: Any?) {
val y1 = when (val either = x as Either) {
is Left -> "L"
is Right -> "R"
}
}
fun testSmartcastToSealedInSubjectInitializer2(x: Any?) {
val y2 = when (val either: Any = x as Either) { // NB explicit type annotation
is Left -> "L"
is Right -> "R"
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +VariableDeclarationInWhenSubject
// !DIAGNOSTICS: -UNUSED_VARIABLE