[FE 1.0] Report USELESS_IS_CHECK if is expression is always false
^KT-47684 Fixed
This commit is contained in:
committed by
teamcityserver
parent
785e2f862c
commit
7b5a5f5682
@@ -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
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -9,7 +9,7 @@ class C() {
|
||||
|
||||
fun test(a : Any?) {
|
||||
if (a is B) {
|
||||
if (a is C) {
|
||||
if (<!USELESS_IS_CHECK!>a is C<!>) {
|
||||
<!DEBUG_INFO_SMARTCAST!>a<!>.bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ fun useEn(x: En) = x
|
||||
fun useEn2(x: En2) = x
|
||||
|
||||
fun bar(x: Any) {
|
||||
if (x is En && x is En2) {
|
||||
if (x is En && <!USELESS_IS_CHECK!>x is En2<!>) {
|
||||
when (<!DEBUG_INFO_SMARTCAST!>x<!>) {
|
||||
En.A -> useEn(<!DEBUG_INFO_SMARTCAST!>x<!>)
|
||||
En2.D -> useEn2(<!DEBUG_INFO_SMARTCAST!>x<!>)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,4 @@ fun String.gah(view:View ?) {
|
||||
if (view is <!UNRESOLVED_REFERENCE!>TextView<!>)
|
||||
view
|
||||
else <!UNRESOLVED_REFERENCE!>TextView<!>() as foo.TextView
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class C() {
|
||||
|
||||
fun test(a : Any?) {
|
||||
if (a is B) {
|
||||
if (a is C) {
|
||||
if (<!USELESS_IS_CHECK!>a is C<!>) {
|
||||
<!DEBUG_INFO_SMARTCAST!>a<!>.bar();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ sealed class B {
|
||||
}
|
||||
|
||||
fun foo(a: A) {
|
||||
if (a !is B) return
|
||||
if (<!USELESS_IS_CHECK!>a !is B<!>) return
|
||||
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (<!DEBUG_INFO_SMARTCAST!>a<!>) {
|
||||
is A.A1 -> ""
|
||||
|
||||
+2
-2
@@ -78,7 +78,7 @@ fun branchedAndNested(x: Any?, y: Any?) {
|
||||
|
||||
|
||||
fun br(y: Any?) {
|
||||
if (myAssert(y is Int) == Unit && myAssert(y is String) == Unit) {
|
||||
if (myAssert(y is Int) == Unit && myAssert(<!USELESS_IS_CHECK!>y is String<!>) == Unit) {
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!>.length
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!>.inc()
|
||||
}
|
||||
@@ -89,7 +89,7 @@ fun branchedAndNestedWithNativeOperators(x: Any?, y: Any?) {
|
||||
equalsTrue(notEqualsNull(nullWhenNotString(x))) // x is String
|
||||
&&
|
||||
(
|
||||
(myAssert(y is Int) == Unit && myAssert(y is String) == Unit) // y is Int, String
|
||||
(myAssert(y is Int) == Unit && myAssert(<!USELESS_IS_CHECK!>y is String<!>) == Unit) // y is Int, String
|
||||
||
|
||||
equalsTrue(isInt(y) && isString(y)) // y is Int, String
|
||||
)
|
||||
|
||||
+2
-2
@@ -45,8 +45,8 @@ fun intersectingInfo2(x: Any?, y: Any?) {
|
||||
// of them is absent in each arg of "||"-operator, so they *shouldn't* lead to smartcast
|
||||
|
||||
if ((isString(x) && !notIsInt(x) && y is String) ||
|
||||
(!notIsString(x) && isString(y) && y is Int) ||
|
||||
(x is String && !notIsInt(y) && x is Int)) {
|
||||
(!notIsString(x) && isString(y) && <!USELESS_IS_CHECK!>y is Int<!>) ||
|
||||
(x is String && !notIsInt(y) && <!USELESS_IS_CHECK!>x is Int<!>)) {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>inc<!>()
|
||||
y.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
|
||||
Reference in New Issue
Block a user