[FIR] Add CAST_NEVER_SUCCEEDS

This commit is contained in:
Ivan Kochurkin
2021-09-16 20:58:52 +03:00
committed by TeamCityServer
parent 4ca757446a
commit 2b5524b18f
42 changed files with 206 additions and 273 deletions
+3 -3
View File
@@ -32,11 +32,11 @@ fun test() {
checkSubtype<Double>(<!ARGUMENT_TYPE_MISMATCH!>1<!>)
checkSubtype<Float>(<!ARGUMENT_TYPE_MISMATCH!>1<!>)
1 as Byte
1 <!CAST_NEVER_SUCCEEDS!>as<!> Byte
1 <!USELESS_CAST!>as Int<!>
0xff as Long
0xff <!CAST_NEVER_SUCCEEDS!>as<!> Long
1.1 as Int
1.1 <!CAST_NEVER_SUCCEEDS!>as<!> Int
checkSubtype<Int>(<!ARGUMENT_TYPE_MISMATCH!>1.1<!>)
varargByte(0x77, 1, 3, <!ARGUMENT_TYPE_MISMATCH!>200<!>, 0b111)
@@ -33,4 +33,4 @@ fun bar(a: Ann = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>) {
operator fun String.invoke() {}
// from stdlib
fun <T> javaClass() : Class<T> = null as Class<T>
fun <T> javaClass() : Class<T> = null <!CAST_NEVER_SUCCEEDS!>as<!> Class<T>
@@ -1,14 +0,0 @@
// Nothing can be cast to Nothing
fun foo(x: String) {
x as Nothing
}
fun gav(y: String?) {
y as Nothing
}
// Only nullable can be cast to Nothing?
fun bar(x: String, y: String?) {
x as Nothing?
y as Nothing?
}
+1
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// Nothing can be cast to Nothing
fun foo(x: String) {
x <!CAST_NEVER_SUCCEEDS!>as<!> Nothing
@@ -1,18 +0,0 @@
typealias MyString = String
val x: MyString = ""
val y = x as Any
interface Base
class Derived : Base
interface Other : Base
typealias IBase = Base
typealias IOther = Other
val ib: IBase = Derived()
val d = ib as Derived
val o = ib as Other
val io = ib as IOther
val s = d as String
val ms = d as MyString
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
typealias MyString = String
val x: MyString = ""
+36 -36
View File
@@ -1,51 +1,51 @@
fun asCall() {
1 <!USELESS_CAST!>as Int<!>
1 as Byte
1 as Short
1 as Long
1 as Char
1 as Double
1 as Float
1 <!CAST_NEVER_SUCCEEDS!>as<!> Byte
1 <!CAST_NEVER_SUCCEEDS!>as<!> Short
1 <!CAST_NEVER_SUCCEEDS!>as<!> Long
1 <!CAST_NEVER_SUCCEEDS!>as<!> Char
1 <!CAST_NEVER_SUCCEEDS!>as<!> Double
1 <!CAST_NEVER_SUCCEEDS!>as<!> Float
1.0 as Int
1.0 as Byte
1.0 as Short
1.0 as Long
1.0 as Char
1.0 <!CAST_NEVER_SUCCEEDS!>as<!> Int
1.0 <!CAST_NEVER_SUCCEEDS!>as<!> Byte
1.0 <!CAST_NEVER_SUCCEEDS!>as<!> Short
1.0 <!CAST_NEVER_SUCCEEDS!>as<!> Long
1.0 <!CAST_NEVER_SUCCEEDS!>as<!> Char
1.0 <!USELESS_CAST!>as Double<!>
1.0 as Float
1.0 <!CAST_NEVER_SUCCEEDS!>as<!> Float
1f as Int
1f as Byte
1f as Short
1f as Long
1f as Char
1f as Double
1f <!CAST_NEVER_SUCCEEDS!>as<!> Int
1f <!CAST_NEVER_SUCCEEDS!>as<!> Byte
1f <!CAST_NEVER_SUCCEEDS!>as<!> Short
1f <!CAST_NEVER_SUCCEEDS!>as<!> Long
1f <!CAST_NEVER_SUCCEEDS!>as<!> Char
1f <!CAST_NEVER_SUCCEEDS!>as<!> Double
1f <!USELESS_CAST!>as Float<!>
}
fun asSafe() {
1 as? Int
1 as? Byte
1 as? Short
1 as? Long
1 as? Char
1 as? Double
1 as? Float
1 <!CAST_NEVER_SUCCEEDS!>as?<!> Byte
1 <!CAST_NEVER_SUCCEEDS!>as?<!> Short
1 <!CAST_NEVER_SUCCEEDS!>as?<!> Long
1 <!CAST_NEVER_SUCCEEDS!>as?<!> Char
1 <!CAST_NEVER_SUCCEEDS!>as?<!> Double
1 <!CAST_NEVER_SUCCEEDS!>as?<!> Float
1.0 as? Int
1.0 as? Byte
1.0 as? Short
1.0 as? Long
1.0 as? Char
1.0 <!CAST_NEVER_SUCCEEDS!>as?<!> Int
1.0 <!CAST_NEVER_SUCCEEDS!>as?<!> Byte
1.0 <!CAST_NEVER_SUCCEEDS!>as?<!> Short
1.0 <!CAST_NEVER_SUCCEEDS!>as?<!> Long
1.0 <!CAST_NEVER_SUCCEEDS!>as?<!> Char
1.0 as? Double
1.0 as? Float
1.0 <!CAST_NEVER_SUCCEEDS!>as?<!> Float
1f as? Int
1f as? Byte
1f as? Short
1f as? Long
1f as? Char
1f as? Double
1f <!CAST_NEVER_SUCCEEDS!>as?<!> Int
1f <!CAST_NEVER_SUCCEEDS!>as?<!> Byte
1f <!CAST_NEVER_SUCCEEDS!>as?<!> Short
1f <!CAST_NEVER_SUCCEEDS!>as?<!> Long
1f <!CAST_NEVER_SUCCEEDS!>as?<!> Char
1f <!CAST_NEVER_SUCCEEDS!>as?<!> Double
1f as? Float
}
@@ -1,33 +0,0 @@
// !DIAGNOSTICS: -PLATFORM_CLASS_MAPPED_TO_KOTLIN -USELESS_CAST
import java.lang.String as JString
import java.lang.CharSequence as JCS
fun test(
s: String,
js: JString,
cs: CharSequence,
jcs: JCS
) {
s as JString
s as JCS
s as CharSequence
s as String
js as JString
js as JCS
js as CharSequence
js as String
cs as JString
cs as JCS
cs as CharSequence
cs as String
jcs as JString
jcs as JCS
jcs as CharSequence
jcs as String
jcs as Int
s as java.lang.Integer
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -PLATFORM_CLASS_MAPPED_TO_KOTLIN -USELESS_CAST
import java.lang.String as JString
import java.lang.CharSequence as JCS
@@ -1,21 +0,0 @@
// !DIAGNOSTICS: -PLATFORM_CLASS_MAPPED_TO_KOTLIN -UNUSED_PARAMETER -ABSTRACT_MEMBER_NOT_IMPLEMENTED -USELESS_CAST
import java.lang.CharSequence as JCS
class JSub: JCS
class Sub: CharSequence
fun test(
s: Sub,
js: JSub,
cs: CharSequence,
jcs: JCS
) {
// js as CharSequence // - this case is not supported due to limitation in PlatformToKotlinClassMap
js as JCS
s as CharSequence
s as JCS
js as Sub
s as JSub
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -PLATFORM_CLASS_MAPPED_TO_KOTLIN -UNUSED_PARAMETER -ABSTRACT_MEMBER_NOT_IMPLEMENTED -USELESS_CAST
import java.lang.CharSequence as JCS
@@ -1,34 +0,0 @@
// !DIAGNOSTICS: -UNCHECKED_CAST
interface Trait1
interface Trait2
open class OClass1
open class OClass2
class FClass1
class FClass2
fun <TP1: OClass1, TP2: OClass2> test(
t1: Trait1,
oc1: OClass1,
fc1: FClass1,
tp1: TP1
) {
t1 as Trait2
t1 as OClass2
t1 as FClass2
t1 as TP2
oc1 as Trait2
oc1 as OClass2
oc1 as FClass2
oc1 as TP2
fc1 as Trait2
fc1 as OClass2
fc1 as FClass2
fc1 as TP2
tp1 as Trait2
tp1 as OClass2
tp1 as FClass2
tp1 as TP2
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNCHECKED_CAST
interface Trait1
interface Trait2
@@ -19,35 +19,35 @@ class Inv<T>() {
fun testInOut() {
In<String>().f("1");
(null as In<in String>).f("1")
(null as In<*>).<!NONE_APPLICABLE!>f<!>("1") // Wrong Arg
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<in String>).f("1")
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<*>).<!NONE_APPLICABLE!>f<!>("1") // Wrong Arg
In<String>().f(1);
(null as In<in String>).f(1)
(null as In<*>).f(1);
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<in String>).f(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<*>).f(1);
Out<Int>().f(1)
(null as Out<out Int>).f(1)
(null as Out<*>).f(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<out Int>).f(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<*>).f(1)
Out<Int>().f()
(null as Out<out Int>).f()
(null as Out<*>).f()
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<out Int>).f()
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<*>).f()
Inv<Int>().f(1)
(null as Inv<in Int>).f(1)
(null as Inv<out Int>).f(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // !!
(null as Inv<*>).f(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).f(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).f(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).f(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // !!
Inv<Int>().inf(1)
(null as Inv<in Int>).inf(1)
(null as Inv<out Int>).inf(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // !!
(null as Inv<*>).inf(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).inf(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).inf(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).inf(<!ARGUMENT_TYPE_MISMATCH!>1<!>) // !!
Inv<Int>().outf()
checkSubtype<Int>(<!ARGUMENT_TYPE_MISMATCH!>(null as Inv<in Int>).outf()<!>) // Type mismatch
(null as Inv<out Int>).outf()
(null as Inv<*>).outf()
checkSubtype<Int>(<!ARGUMENT_TYPE_MISMATCH!>(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).outf()<!>) // Type mismatch
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).outf()
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).outf()
Inv<Int>().outf(<!TOO_MANY_ARGUMENTS!>1<!>) // Wrong Arg
}
@@ -9,4 +9,4 @@ fun <T> foo2(): T = TODO()
val test = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo2<!>().plus("") <!USELESS_CAST!>as String<!>
fun <T> T.bar() = this
val barTest = "".bar() as Number
val barTest = "".bar() <!CAST_NEVER_SUCCEEDS!>as<!> Number
@@ -1,11 +0,0 @@
fun <R> runCatching(block: () -> R) = null as Result<R>
class Result<out T> {
fun getOrNull(): T? = null
}
fun main() {
runCatching {
null
}.getOrNull() // don't report IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun <R> runCatching(block: () -> R) = null <!CAST_NEVER_SUCCEEDS!>as<!> Result<R>
class Result<out T> {
@@ -52,7 +52,7 @@ fun test() {
if (<!USELESS_IS_CHECK!>x11 is Foo<<!UNRESOLVED_REFERENCE!>_<!>><!>) { }
x10 as <!UNRESOLVED_REFERENCE!>_<!>
x10 as Foo<<!UNRESOLVED_REFERENCE!>_<!>>
x10 <!CAST_NEVER_SUCCEEDS!>as<!> Foo<<!UNRESOLVED_REFERENCE!>_<!>>
val x12: Foo<@<!UNDERSCORE_USAGE_WITHOUT_BACKTICKS, UNRESOLVED_REFERENCE!>_<!> Int>? = null
val x13: Foo<@<!UNDERSCORE_USAGE_WITHOUT_BACKTICKS, UNRESOLVED_REFERENCE!>_<!>() Int>? = null
@@ -1,17 +0,0 @@
// KT-702 Type inference failed
fun <T> getJavaClass() : java.lang.Class<T> { return "" as Class<T> }
public class Throwables() {
companion object {
public fun <X : Throwable?> propagateIfInstanceOf(throwable : Throwable?, declaredType : Class<X?>?) {
if (((throwable != null) && declaredType?.isInstance(throwable)!!))
{
throw <!SAFE_CALL_WILL_CHANGE_NULLABILITY!>declaredType<!UNNECESSARY_SAFE_CALL!>?.<!>cast(throwable)<!>!!
}
}
public fun propagateIfPossible(throwable : Throwable?) {
propagateIfInstanceOf(throwable, getJavaClass<Error?>()) //; Type inference failed: Mismatch while expanding constraints
propagateIfInstanceOf(throwable, getJavaClass<RuntimeException?>()) // Type inference failed: Mismatch while expanding constraints
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// KT-702 Type inference failed
fun <T> getJavaClass() : java.lang.Class<T> { return "" <!CAST_NEVER_SUCCEEDS!>as<!> Class<T> }
@@ -2,7 +2,7 @@
class TypeInfo<T>
fun <T> typeinfo() : TypeInfo<T> = null as TypeInfo<T>
fun <T> typeinfo() : TypeInfo<T> = null <!CAST_NEVER_SUCCEEDS!>as<!> TypeInfo<T>
fun <T> TypeInfo<T>.getJavaClass() : java.lang.Class<T> {
val t : java.lang.Object = this as java.lang.Object
@@ -13,4 +13,4 @@ fun <T> getJavaClass() = typeinfo<T>().getJavaClass()
fun main() {
System.out.println(getJavaClass<String>())
}
}
@@ -43,7 +43,7 @@ fun f(a: SomeClass?) {
aa<!UNSAFE_CALL!>.<!>hashCode()
aa.<!UNRESOLVED_REFERENCE!>foo<!>
(aa as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
(aa as SomeSubClass).foo
(aa <!CAST_NEVER_SUCCEEDS!>as<!> SomeSubClass).foo
}
val b = (aa as? SomeSubClass)?.foo
aa = null
@@ -52,7 +52,7 @@ fun f(a: SomeClass?) {
aa<!UNSAFE_CALL!>.<!>hashCode()
aa.<!UNRESOLVED_REFERENCE!>foo<!>
(aa as? SomeSubClass)<!UNSAFE_CALL!>.<!>foo
(aa as SomeSubClass).foo
(aa <!CAST_NEVER_SUCCEEDS!>as<!> SomeSubClass).foo
}
aa = a
val c = aa as? SomeSubClass
@@ -4,7 +4,7 @@ fun <T : CharSequence> foo(x: Array<Any>, y: IntArray, block: (T, Int) -> Int) {
@Suppress("UNCHECKED_CAST")
// comment
/* comment */
r = block(x[0] as T, "" as Int)
r = block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int)
// to prevent unused assignment diagnostic for the above statement
r.hashCode()
@@ -13,42 +13,42 @@ fun <T : CharSequence> foo(x: Array<Any>, y: IntArray, block: (T, Int) -> Int) {
if (i != 1) {
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
}
if (i != 1)
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
if (i != 2)
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
else
@Suppress("UNCHECKED_CAST")
i += block(x[1] as T, "" as Int).toInt()
i += block(x[1] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
while (i != 1)
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
do
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
while (i != 1)
for (j in 1..100)
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
when (i) {
1 ->
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
}
val l: () -> Unit = {
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
}
l()
@@ -56,5 +56,5 @@ fun <T : CharSequence> foo(x: Array<Any>, y: IntArray, block: (T, Int) -> Int) {
@Suppress("UNCHECKED_CAST")
y[i] += block(x[0] as T, "" as Int).toInt()
y[i] += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
}
@@ -1,7 +1,7 @@
fun <T : CharSequence> foo(x: Array<Any>, block: (T, Int) -> Int) {
var r: Any?
@Suppress("UNCHECKED_CAST") r = block(x[0] as T, "" as Int)
@Suppress("UNCHECKED_CAST") r = block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int)
// to prevent unused assignment diagnostic for the above statement
r.hashCode()
@@ -9,11 +9,11 @@ fun <T : CharSequence> foo(x: Array<Any>, block: (T, Int) -> Int) {
var i = 1
if (i != 1) {
@Suppress("UNCHECKED_CAST") i += block(x[0] as T, "" as Int).toInt()
@Suppress("UNCHECKED_CAST") i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
}
if (i != 1) @Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" as Int).toInt()
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
if (i != 1) @Suppress("UNCHECKED_CAST") i += block(x[0] as T, "" as Int).toInt()
if (i != 1) @Suppress("UNCHECKED_CAST") i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
}
@@ -8,5 +8,5 @@ fun interface ReadOnlyProperty<in T, out V> {
class Problem {
val variable: Int by <!DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH, NEW_INFERENCE_ERROR, NEW_INFERENCE_ERROR!>delegate()<!> // delegate returns `ReadOnlyProperty<Problem, {CharSequence & Int}>`
fun <T : CharSequence> delegate() = null as ReadOnlyProperty<Problem, T>
fun <T : CharSequence> delegate() = null <!CAST_NEVER_SUCCEEDS!>as<!> ReadOnlyProperty<Problem, T>
}
@@ -13,7 +13,7 @@ fun test1(s: SubInt, sWrong: SubIntWrong) {
val a = "foo"
foo(<!ARGUMENT_TYPE_MISMATCH!>a<!>)
a as (Int, String) -> String
a <!CAST_NEVER_SUCCEEDS!>as<!> (Int, String) -> String
foo(<!ARGUMENT_TYPE_MISMATCH!>a<!>)
}