[FE 1.0] Report USELESS_IS_CHECK if is expression is always false

^KT-47684 Fixed
This commit is contained in:
Dmitriy Novozhilov
2021-07-09 14:03:48 +03:00
committed by teamcityserver
parent 785e2f862c
commit 7b5a5f5682
24 changed files with 283 additions and 59 deletions
@@ -2,5 +2,5 @@ open class RecA<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>RecB<T><!>()
open class RecB<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>RecA<T><!>()
open class SelfR<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>SelfR<T><!>()
fun test(f: SelfR<String>) = f is <!CANNOT_CHECK_FOR_ERASED!>RecA<String><!>
fun test(f: RecB<String>) = f is <!CANNOT_CHECK_FOR_ERASED!>RecA<String><!>
fun test(f: SelfR<String>) = <!USELESS_IS_CHECK!>f is <!CANNOT_CHECK_FOR_ERASED!>RecA<String><!><!>
fun test(f: RecB<String>) = <!USELESS_IS_CHECK!>f is <!CANNOT_CHECK_FOR_ERASED!>RecA<String><!><!>
@@ -0,0 +1,69 @@
abstract class A
abstract class B : A()
abstract class AS
abstract class BS : AS()
interface AI
interface BI : AI
fun test_1(a: A) {
<!USELESS_IS_CHECK!>a is A<!> // always true
a is B
a is AS // always false
a is BS // always false
a is AI
a is BI
}
fun test_2(a: A) {
<!USELESS_IS_CHECK!>a !is A<!> // always false
a !is B
a !is AS // always true
a !is BS // always true
a !is AI
a !is BI
}
fun test_3(a: Any) {
if (a is A) {
<!USELESS_IS_CHECK!>a is A<!> // always true
a is B
a is AS // always false
a is BS // always false
a is AI
a is BI
}
}
fun test_4(a: A) {
when (a) {
<!USELESS_IS_CHECK!>is A<!> -> {} // always true
is B -> {}
is AS -> {} // always false
is BS -> {} // always false
is AI -> {}
is BI -> {}
}
}
fun test_5(a: A) {
when (a) {
<!USELESS_IS_CHECK!>!is A<!> -> {} // always false
!is B -> {}
!is AS -> {} // always true
!is BS -> {} // here a may has type AS (by data flow)
!is AI -> {}
!is BI -> {}
}
}
@@ -0,0 +1,69 @@
abstract class A
abstract class B : A()
abstract class AS
abstract class BS : AS()
interface AI
interface BI : AI
fun test_1(a: A) {
<!USELESS_IS_CHECK("true")!>a is A<!> // always true
a is B
<!USELESS_IS_CHECK("false")!>a is AS<!> // always false
<!USELESS_IS_CHECK("false")!>a is BS<!> // always false
a is AI
a is BI
}
fun test_2(a: A) {
<!USELESS_IS_CHECK("false")!>a !is A<!> // always false
a !is B
<!USELESS_IS_CHECK("true")!>a !is AS<!> // always true
<!USELESS_IS_CHECK("true")!>a !is BS<!> // always true
a !is AI
a !is BI
}
fun test_3(a: Any) {
if (a is A) {
<!USELESS_IS_CHECK("true")!>a is A<!> // always true
a is B
<!USELESS_IS_CHECK("false")!>a is AS<!> // always false
<!USELESS_IS_CHECK("false")!>a is BS<!> // always false
a is AI
a is BI
}
}
fun test_4(a: A) {
when (a) {
<!USELESS_IS_CHECK("true")!>is A<!> -> {} // always true
is B -> {}
<!USELESS_IS_CHECK("false")!>is AS<!> -> {} // always false
<!USELESS_IS_CHECK("false")!>is BS<!> -> {} // always false
is AI -> {}
is BI -> {}
}
}
fun test_5(a: A) {
when (a) {
<!USELESS_IS_CHECK("false")!>!is A<!> -> {} // always false
!is B -> {}
<!USELESS_IS_CHECK("true")!>!is AS<!> -> {} // always true
!is BS -> {} // here a may has type AS (by data flow)
!is AI -> {}
!is BI -> {}
}
}
@@ -0,0 +1,48 @@
package
public fun test_1(/*0*/ a: A): kotlin.Unit
public fun test_2(/*0*/ a: A): kotlin.Unit
public fun test_3(/*0*/ a: kotlin.Any): kotlin.Unit
public fun test_4(/*0*/ a: A): kotlin.Unit
public fun test_5(/*0*/ a: A): kotlin.Unit
public abstract class A {
public constructor A()
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 interface AI {
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 abstract class AS {
public constructor AS()
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 abstract class B : A {
public constructor B()
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 interface BI : AI {
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 abstract class BS : AS {
public constructor BS()
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
}