Detect redundant 'is' check
#KT-14187 Fixed
This commit is contained in:
committed by
Mikhail Zarechenskiy
parent
768e0fa738
commit
cd24adac32
+2
-2
@@ -18,11 +18,11 @@ class MyColor(val x: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>, y: Color.<!ENUM_ENTRY_A
|
||||
fun local(arg: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!>): Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> = arg
|
||||
val temp: Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> = <!TYPE_MISMATCH!>Color.RED<!>
|
||||
temp <!USELESS_CAST!>as? Color.<!ENUM_ENTRY_AS_TYPE!>RED<!><!>
|
||||
if (temp is <!IS_ENUM_ENTRY!>Color.<!ENUM_ENTRY_AS_TYPE!>RED<!><!>) {
|
||||
if (<!USELESS_IS_CHECK!>temp is <!IS_ENUM_ENTRY!>Color.<!ENUM_ENTRY_AS_TYPE!>RED<!><!><!>) {
|
||||
return temp <!USELESS_CAST!>as Color.<!ENUM_ENTRY_AS_TYPE!>RED<!><!>
|
||||
}
|
||||
val obj = object : Color.<!ENUM_ENTRY_AS_TYPE!>RED<!> {}
|
||||
if (obj is <!IS_ENUM_ENTRY!>Color.<!ENUM_ENTRY_AS_TYPE!>RED<!><!>) {
|
||||
if (<!USELESS_IS_CHECK!>obj is <!IS_ENUM_ENTRY!>Color.<!ENUM_ENTRY_AS_TYPE!>RED<!><!><!>) {
|
||||
return obj
|
||||
}
|
||||
return <!TYPE_MISMATCH!>Color.RED<!>
|
||||
|
||||
+20
-1
@@ -1,7 +1,26 @@
|
||||
// FILE: KotlinFile.kt
|
||||
|
||||
fun test() {
|
||||
if (1 is Int) {
|
||||
if (<!USELESS_IS_CHECK!>1 is Int<!>) {
|
||||
if (1 is <!INCOMPATIBLE_TYPES!>Boolean<!>) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
A.create() is A
|
||||
<!USELESS_IS_CHECK!>A.create() is A?<!>
|
||||
|
||||
<!UNRESOLVED_REFERENCE!>unresolved<!> is A
|
||||
<!UNRESOLVED_REFERENCE!>unresolved<!> is A?
|
||||
|
||||
val x = foo()
|
||||
x as String
|
||||
<!USELESS_IS_CHECK!>x is String<!>
|
||||
}
|
||||
|
||||
fun foo(): Any = ""
|
||||
|
||||
// FILE: A.java
|
||||
class A {
|
||||
static A create() { return null; }
|
||||
}
|
||||
@@ -1,3 +1,14 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Any
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public/*package*/ open class A {
|
||||
public/*package*/ 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
|
||||
|
||||
// Static members
|
||||
public/*package*/ open fun create(): A!
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ fun cannotBe() {
|
||||
<!VARIABLE_EXPECTED!>foo()<!> = Unit;
|
||||
|
||||
(<!VARIABLE_EXPECTED!>i <!USELESS_CAST!>as Int<!><!>) = 34
|
||||
(<!VARIABLE_EXPECTED!>i is Int<!>) = false
|
||||
(<!USELESS_IS_CHECK, VARIABLE_EXPECTED!>i is Int<!>) = false
|
||||
<!VARIABLE_EXPECTED!>A()<!> = A()
|
||||
<!VARIABLE_EXPECTED!>5<!> = 34
|
||||
}
|
||||
|
||||
@@ -45,10 +45,10 @@ fun test(a: Any) {
|
||||
.0f<!UNSUPPORTED!>in<!> a
|
||||
.0<!UNSUPPORTED, UNRESOLVED_REFERENCE!>din<!> a
|
||||
|
||||
1<!UNSUPPORTED!>is<!> Any
|
||||
<!USELESS_IS_CHECK!>1<!UNSUPPORTED!>is<!> Any<!>
|
||||
1<!UNSUPPORTED!>as<!> Any
|
||||
1<!UNSUPPORTED!>as?<!> Any
|
||||
|
||||
1<!UNSUPPORTED!>!is<!> Any
|
||||
<!USELESS_IS_CHECK!>1<!UNSUPPORTED!>!is<!> Any<!>
|
||||
1<!UNSUPPORTED!>!in<!> a
|
||||
}
|
||||
@@ -31,7 +31,8 @@ fun test(a: Any) {
|
||||
a <!UNSUPPORTED!>!in<!>'s'
|
||||
a <!UNSUPPORTED!>!in<!><!EMPTY_CHARACTER_LITERAL!>''<!>
|
||||
|
||||
if("s"<!UNSUPPORTED!>is<!> Any) {}
|
||||
if(<!USELESS_IS_CHECK!>"s"<!UNSUPPORTED!>is<!> Any<!>) {}
|
||||
if(<!USELESS_IS_CHECK!>"s"<!UNSUPPORTED!>is<!> Any<!>) {}
|
||||
test("s"<!UNSUPPORTED!>as<!> Any)
|
||||
|
||||
a <!UNSUPPORTED!>foo<!>""<!UNSUPPORTED, SYNTAX!>1<!>
|
||||
|
||||
@@ -26,7 +26,7 @@ fun foo() {
|
||||
}
|
||||
|
||||
fun bar(a: Ann = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>) {
|
||||
if (a is Ann) {}
|
||||
if (<!USELESS_IS_CHECK!>a is Ann<!>) {}
|
||||
}
|
||||
|
||||
operator fun String.invoke() {}
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@ open class Base<A>
|
||||
class Some: Base<Int>()
|
||||
|
||||
// a is Some => a is Base<Int>
|
||||
fun f(a: Some) = a is Base<Int>
|
||||
fun f(a: Some) = <!USELESS_IS_CHECK!>a is Base<Int><!>
|
||||
Vendored
+1
-1
@@ -5,4 +5,4 @@ open class Base<in T>
|
||||
class SubBase: Base<A>()
|
||||
|
||||
// f is SubBase => f is Base<A> => (Base<Contravariant T>, B <: A) f is Base<B>
|
||||
fun test(f: SubBase) = f is Base<B>
|
||||
fun test(f: SubBase) = <!USELESS_IS_CHECK!>f is Base<B><!>
|
||||
+1
-1
@@ -5,4 +5,4 @@ open class Base<out T>
|
||||
class SubBase: Base<B>()
|
||||
|
||||
// f is SubBase => (SubBase <: Base<B>) f is Base<B> => (B <: A, Base<Covariant T> => SubBase <: Base<A>) f is Base<A>
|
||||
fun test(f: SubBase) = f is Base<A>
|
||||
fun test(f: SubBase) = <!USELESS_IS_CHECK!>f is Base<A><!>
|
||||
@@ -1 +1 @@
|
||||
fun f(a: MutableList<out Number>) = a is MutableList<out Any>
|
||||
fun f(a: MutableList<out Number>) = <!USELESS_IS_CHECK!>a is MutableList<out Any><!>
|
||||
|
||||
@@ -1 +1 @@
|
||||
fun f(a: MutableList<String>) = a is MutableList<out CharSequence>
|
||||
fun f(a: MutableList<String>) = <!USELESS_IS_CHECK!>a is MutableList<out CharSequence><!>
|
||||
|
||||
@@ -1 +1 @@
|
||||
fun f(a: List<Number>) = a is List<Any>
|
||||
fun f(a: List<Number>) = <!USELESS_IS_CHECK!>a is List<Any><!>
|
||||
|
||||
@@ -1 +1 @@
|
||||
fun <T> testing(a: T) = a is T
|
||||
fun <T> testing(a: T) = <!USELESS_IS_CHECK!>a is T<!>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
fun <T, S : T> test(x: T?, y: S, z: T) {
|
||||
x is <!CANNOT_CHECK_FOR_ERASED!>T<!>
|
||||
x is T?
|
||||
<!USELESS_IS_CHECK!>x is T?<!>
|
||||
|
||||
y is T
|
||||
y is S
|
||||
y is T?
|
||||
y is S?
|
||||
<!USELESS_IS_CHECK!>y is T<!>
|
||||
<!USELESS_IS_CHECK!>y is S<!>
|
||||
<!USELESS_IS_CHECK!>y is T?<!>
|
||||
<!USELESS_IS_CHECK!>y is S?<!>
|
||||
|
||||
z is T
|
||||
z is T?
|
||||
<!USELESS_IS_CHECK!>z is T<!>
|
||||
<!USELESS_IS_CHECK!>z is T?<!>
|
||||
|
||||
<!UNCHECKED_CAST!>null as T<!>
|
||||
null <!USELESS_CAST!>as T?<!>
|
||||
@@ -22,6 +22,6 @@ inline fun <reified T> test(x: T?) {
|
||||
}
|
||||
|
||||
fun <T> foo(x: List<T>, y: List<T>?) {
|
||||
x is List<T>
|
||||
<!USELESS_IS_CHECK!>x is List<T><!>
|
||||
y is List<T>
|
||||
}
|
||||
@@ -22,17 +22,17 @@ public class JavaClass {
|
||||
// FILE: test.kt
|
||||
|
||||
fun <T, S: Any> test(x1: T, x2: T?, y1: S, y2: S?) {
|
||||
x1 is T?
|
||||
x2 is T?
|
||||
y1 is S<!USELESS_NULLABLE_CHECK!>?<!>
|
||||
y2 is S?
|
||||
<!USELESS_IS_CHECK!>x1 is T?<!>
|
||||
<!USELESS_IS_CHECK!>x2 is T?<!>
|
||||
<!USELESS_IS_CHECK!>y1 is S<!USELESS_NULLABLE_CHECK!>?<!><!>
|
||||
<!USELESS_IS_CHECK!>y2 is S?<!>
|
||||
|
||||
val f1 = JavaClass.foo()
|
||||
f1 is Int?
|
||||
<!USELESS_IS_CHECK!>f1 is Int?<!>
|
||||
|
||||
val f2 = JavaClass.fooN()
|
||||
f2 is Int?
|
||||
<!USELESS_IS_CHECK!>f2 is Int?<!>
|
||||
|
||||
val f3 = JavaClass.fooNN()
|
||||
f3 is Int<!USELESS_NULLABLE_CHECK!>?<!>
|
||||
<!USELESS_IS_CHECK!>f3 is Int<!USELESS_NULLABLE_CHECK!>?<!><!>
|
||||
}
|
||||
Vendored
+1
-1
@@ -38,7 +38,7 @@ fun t1(b : Boolean) {
|
||||
return;
|
||||
}
|
||||
doSmth(i)
|
||||
if (i is Int) {
|
||||
if (<!USELESS_IS_CHECK!>i is Int<!>) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ fun t1(x: Int) = when(<!UNUSED_EXPRESSION!>x<!>) {
|
||||
}
|
||||
|
||||
fun t5(x: Int) = <!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is Int -> 1
|
||||
<!USELESS_IS_CHECK!>is Int<!> -> 1
|
||||
2 -> 2
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
fun foo(x: Number) {
|
||||
if ((x as Int) is Int) {
|
||||
if (<!USELESS_IS_CHECK!>(x as Int) is Int<!>) {
|
||||
checkSubtype<Int>(<!DEBUG_INFO_SMARTCAST!>x<!>)
|
||||
}
|
||||
checkSubtype<Int>(<!DEBUG_INFO_SMARTCAST!>x<!>)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
fun noUselessDataFlowInfoCreation(x: Number) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) {
|
||||
if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) {
|
||||
if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) {
|
||||
if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) {
|
||||
if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) { if (<!USELESS_IS_CHECK!>x is Int<!>) {
|
||||
} } } } } } } } } } } } } } } } } } } } } } } } }
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ class DerivedOuter<G> : SuperOuter<G>() {
|
||||
}
|
||||
|
||||
fun bare(x: SuperOuter<*>.SuperInner<*>, y: Any?) {
|
||||
if (x is SuperOuter.SuperInner) return
|
||||
if (<!USELESS_IS_CHECK!>x is SuperOuter.SuperInner<!>) return
|
||||
if (y is <!NO_TYPE_ARGUMENTS_ON_RHS!>SuperOuter.SuperInner<!>) {
|
||||
return
|
||||
}
|
||||
|
||||
+5
-5
@@ -35,7 +35,7 @@ fun f10(init : A?) {
|
||||
if (!(a is B)) {
|
||||
return;
|
||||
}
|
||||
if (!(a is B)) {
|
||||
if (!(<!USELESS_IS_CHECK!>a is B<!>)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ fun f11(a : A?) {
|
||||
is B -> <!DEBUG_INFO_SMARTCAST!>a<!>.bar()
|
||||
is A -> <!DEBUG_INFO_SMARTCAST!>a<!>.foo()
|
||||
is Any -> <!DEBUG_INFO_SMARTCAST!>a<!>.foo()
|
||||
is Any? -> a.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
<!USELESS_IS_CHECK!>is Any?<!> -> a.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
else -> a?.foo()
|
||||
}
|
||||
}
|
||||
@@ -67,12 +67,12 @@ fun f12(a : A?) {
|
||||
is B -> <!DEBUG_INFO_SMARTCAST!>a<!>.bar()
|
||||
is A -> <!DEBUG_INFO_SMARTCAST!>a<!>.foo()
|
||||
is Any -> <!DEBUG_INFO_SMARTCAST!>a<!>.foo();
|
||||
is Any? -> a.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
<!USELESS_IS_CHECK!>is Any?<!> -> a.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
is C -> <!DEBUG_INFO_SMARTCAST!>a<!>.bar()
|
||||
else -> a?.foo()
|
||||
}
|
||||
|
||||
if (a is Any?) {
|
||||
if (<!USELESS_IS_CHECK!>a is Any?<!>) {
|
||||
a?.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
}
|
||||
if (a is B) {
|
||||
@@ -197,7 +197,7 @@ fun mergeSmartCasts(a: Any?) {
|
||||
when (a) {
|
||||
is String, is Any -> a.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
|
||||
}
|
||||
if (a is String && a is Any) {
|
||||
if (a is String && <!USELESS_IS_CHECK!>a is Any<!>) {
|
||||
val <!UNUSED_VARIABLE!>i<!>: Int = <!DEBUG_INFO_SMARTCAST!>a<!>.compareTo("")
|
||||
}
|
||||
if (a is String && <!DEBUG_INFO_SMARTCAST!>a<!>.compareTo("") == 0) {}
|
||||
|
||||
+2
-2
@@ -5,6 +5,6 @@ inline public fun reg(converter: (Any) -> Any, flag: Boolean) {
|
||||
}
|
||||
|
||||
public inline fun register(converter: (Any) -> Any) {
|
||||
<!USAGE_IS_NOT_INLINABLE!>converter<!> is (Any) -> Any
|
||||
reg(converter, <!USAGE_IS_NOT_INLINABLE!>converter<!> is (Any) -> Any)
|
||||
<!USELESS_IS_CHECK!><!USAGE_IS_NOT_INLINABLE!>converter<!> is (Any) -> Any<!>
|
||||
reg(converter, <!USELESS_IS_CHECK!><!USAGE_IS_NOT_INLINABLE!>converter<!> is (Any) -> Any<!>)
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@ inline public fun reg(converter: (Any) -> Any) {
|
||||
|
||||
public inline fun register(converter: (Any) -> Any) {
|
||||
reg(when(<!USAGE_IS_NOT_INLINABLE!>converter<!>) {
|
||||
is (Any) -> Any -> <!USAGE_IS_NOT_INLINABLE!>converter<!>
|
||||
<!USELESS_IS_CHECK!>is (Any) -> Any<!> -> <!USAGE_IS_NOT_INLINABLE!>converter<!>
|
||||
else -> <!USAGE_IS_NOT_INLINABLE!>converter<!>
|
||||
})
|
||||
}
|
||||
@@ -9,7 +9,7 @@ sealed class Expr : Stmt() {
|
||||
fun test(x: Stmt): String =
|
||||
when (x) {
|
||||
is Expr -> "expr"
|
||||
is Stmt -> "stmt"
|
||||
<!USELESS_IS_CHECK!>is Stmt<!> -> "stmt"
|
||||
}
|
||||
|
||||
fun test2(x: Stmt): String =
|
||||
@@ -19,5 +19,5 @@ fun test2(x: Stmt): String =
|
||||
|
||||
fun test3(x: Expr): String =
|
||||
when (x) {
|
||||
is Stmt -> "stmt"
|
||||
<!USELESS_IS_CHECK!>is Stmt<!> -> "stmt"
|
||||
}
|
||||
@@ -9,7 +9,7 @@ sealed class Sealed {
|
||||
fun foo(s: Sealed): Int {
|
||||
return <!NO_ELSE_IN_WHEN!>when<!>(s) {
|
||||
is Sealed.First -> 1
|
||||
!is Any -> 0
|
||||
<!USELESS_IS_CHECK!>!is Any<!> -> 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ interface B<T> : A<T>
|
||||
fun <T> foo(b: A<T>) = b
|
||||
|
||||
fun <T> test(a: A<T>) {
|
||||
if (a is Any) {
|
||||
if (<!USELESS_IS_CHECK!>a is Any<!>) {
|
||||
// Error:(9, 9) Kotlin: Type inference failed: fun <T> foo(b: A<T>): kotlin.Unit
|
||||
// cannot be applied to (A<T>)
|
||||
foo(a)
|
||||
|
||||
+3
-2
@@ -5,8 +5,9 @@ fun foo() : Int {
|
||||
val x = 1
|
||||
when (x) {
|
||||
is <!INCOMPATIBLE_TYPES!>String<!> -> <!UNUSED_EXPRESSION!>1<!>
|
||||
!is Int -> <!UNUSED_EXPRESSION!>1<!>
|
||||
is Any<!USELESS_NULLABLE_CHECK!>?<!> -> <!UNUSED_EXPRESSION!>1<!>
|
||||
<!USELESS_IS_CHECK!>!is Int<!> -> <!UNUSED_EXPRESSION!>1<!>
|
||||
<!USELESS_IS_CHECK!>is Any<!USELESS_NULLABLE_CHECK!>?<!><!> -> <!UNUSED_EXPRESSION!>1<!>
|
||||
<!USELESS_IS_CHECK!>is Any<!> -> <!UNUSED_EXPRESSION!>1<!>
|
||||
<!INCOMPATIBLE_TYPES!>s<!> -> <!UNUSED_EXPRESSION!>1<!>
|
||||
1 -> <!UNUSED_EXPRESSION!>1<!>
|
||||
1 + <!UNRESOLVED_REFERENCE!>a<!> -> <!UNUSED_EXPRESSION!>1<!>
|
||||
|
||||
Reference in New Issue
Block a user