Fix for KT-7999: Wrong result when use nullable types as reified parameter, KT-8043: Unsafe cast to reified parameter throws NPE instead of TypeCastException

#KT-7999 Fixed
  #KT-8043 Fixed

~
This commit is contained in:
Michael Bogdanov
2015-11-28 12:32:11 +03:00
parent 3478a6fb6c
commit 4b8017e34b
37 changed files with 756 additions and 40 deletions
@@ -0,0 +1,36 @@
import test.*
fun box(): String {
if (null.foo3<Any>() != null) return "fail 1"
if (null.foo3<Any?>() != null) return "fail 2"
if (null.foo3<A>() != null) return "fail 3"
if (null.foo3<A?>() != null) return "fail 4"
val a = A()
if (a.foo3<Any>() != a) return "fail 5"
if (a.foo3<Any?>() != a) return "fail 6"
if (a.foo3<A>() != a) return "fail 7"
if (a.foo3<A?>() != a) return "fail 8"
val b = B()
failClassCast { b.foo3<A>(); return "failTypeCast 9" }
failClassCast { b.foo3<A?>(); return "failTypeCast 10" }
return "OK"
}
inline fun failClassCast(s: () -> Unit) {
try {
s()
}
catch (e: TypeCastException) {
throw e
}
catch (e: ClassCastException) {
}
}
@@ -0,0 +1,10 @@
package test
class A
class B
inline fun <reified T> Any?.foo(): T = this as T
inline fun <reified Y> Any?.foo2(): Y? = foo<Y?>()
inline fun <reified Z> Any?.foo3(): Z? = foo2<Z>()
@@ -0,0 +1,18 @@
import test.*
fun case1(): Int =
null.castTo<Int?, Int>()
fun box(): String {
failTypeCast { case1(); return "failTypeCast 9" }
return "OK"
}
inline fun failTypeCast(s: () -> Unit) {
try {
s()
}
catch (e: TypeCastException) {
}
}
@@ -0,0 +1,3 @@
package test
inline fun <reified T, reified R>T.castTo(): R = this as R
@@ -0,0 +1,10 @@
import test.*
fun box(): String {
val a = A()
if (a.foo<Any>() != a) return "failTypeCast 5"
return "OK"
}
@@ -0,0 +1,13 @@
package test
class A
fun call(a: String, b: String, c: String, d: String, e: String, f: Any) {
}
inline fun <reified T: Any> Any?.foo(): T {
call("1", "2", "3", "4", "5", this as T)
return this as T
}
@@ -0,0 +1,45 @@
import test.*
fun box(): String {
if (null.foo<Any>() != null) return "failTypeCast 1"
if (null.foo<Any?>() != null) return "failTypeCast 2"
if (null.foo<A>() != null) return "failTypeCast 3"
if (null.foo<A?>() != null) return "failTypeCast 4"
val a = A()
if (a.foo<Any>() != a) return "failTypeCast 5"
if (a.foo<Any?>() != a) return "failTypeCast 6"
if (a.foo<A>() != a) return "failTypeCast 7"
if (a.foo<A?>() != a) return "failTypeCast 8"
val b = B()
failClassCast { b.foo<A>(); return "failTypeCast 9" }
failClassCast { b.foo<A?>(); return "failTypeCast 10" }
return "OK"
}
inline fun failTypeCast(s: () -> Unit) {
try {
s()
}
catch (e: TypeCastException) {
}
}
inline fun failClassCast(s: () -> Unit) {
try {
s()
}
catch (e: TypeCastException) {
throw e
}
catch (e: ClassCastException) {
}
}
@@ -0,0 +1,6 @@
package test
class A
class B
inline fun <reified T> Any?.foo(): T? = this as T?
@@ -0,0 +1,45 @@
import test.*
fun box(): String {
failTypeCast { null.foo<Any>(); return "failTypeCast 1" }
if (null.foo<Any?>() != null) return "failTypeCast 2"
failTypeCast { null.foo<A>(); return "failTypeCast 3" }
if (null.foo<A?>() != null) return "failTypeCast 4"
val a = A()
if (a.foo<Any>() != a) return "failTypeCast 5"
if (a.foo<Any?>() != a) return "failTypeCast 6"
if (a.foo<A>() != a) return "failTypeCast 7"
if (a.foo<A?>() != a) return "failTypeCast 8"
val b = B()
failClassCast { b.foo<A>(); return "failTypeCast 9" }
failClassCast { b.foo<A?>(); return "failTypeCast 10" }
return "OK"
}
inline fun failTypeCast(s: () -> Unit) {
try {
s()
}
catch (e: TypeCastException) {
}
}
inline fun failClassCast(s: () -> Unit) {
try {
s()
}
catch (e: TypeCastException) {
throw e
}
catch (e: ClassCastException) {
}
}
@@ -0,0 +1,6 @@
package test
class A
class B
inline fun <reified T> Any?.foo(): T = this as T
@@ -0,0 +1,45 @@
import test.*
fun box(): String {
if (null.foo<Any>() != null) return "failTypeCast 1"
if (null.foo<Any?>() != null) return "failTypeCast 2"
if (null.foo<A>() != null) return "failTypeCast 3"
if (null.foo<A?>() != null) return "failTypeCast 4"
val a = A()
if (a.foo<Any>() != a) return "failTypeCast 5"
if (a.foo<Any?>() != a) return "failTypeCast 6"
if (a.foo<A>() != a) return "failTypeCast 7"
if (a.foo<A?>() != a) return "failTypeCast 8"
val b = B()
if (b.foo<A>() != null) return "fail 9"
if (b.foo<A?>() != null) return "fail 10"
return "OK"
}
inline fun failTypeCast(s: () -> Unit) {
try {
s()
}
catch (e: TypeCastException) {
}
}
inline fun failClassCast(s: () -> Unit) {
try {
s()
}
catch (e: TypeCastException) {
throw e
}
catch (e: ClassCastException) {
}
}
@@ -0,0 +1,6 @@
package test
class A
class B
inline fun <reified T> Any?.foo(): T? = this as? T
@@ -0,0 +1,24 @@
import test.*
fun box(): String {
if (null.foo3<Any>() != true) return "fail 1"
if (null.foo3<Any?>() != true) return "fail 2"
if (null.foo3<A>() != true) return "fail 3"
if (null.foo3<A?>() != true) return "fail 4"
val a = A()
if (a.foo3<Any>() != true) return "fail 5"
if (a.foo3<Any?>() != true) return "fail 6"
if (a.foo3<A>() != true) return "fail 7"
if (a.foo3<A?>() != true) return "fail 8"
val b = B()
if (b.foo3<A>() != false) return "fail 9"
if (b.foo3<A?>() != false) return "fail 10"
return "OK"
}
@@ -0,0 +1,10 @@
package test
class A
class B
inline fun <reified T> Any?.foo() = this is T
inline fun <reified Y> Any?.foo2() = foo<Y?>()
inline fun <reified Z> Any?.foo3() = foo2<Z>()
@@ -0,0 +1,24 @@
import test.*
fun box(): String {
if (null.foo<Any>() != true) return "fail 1"
if (null.foo<Any?>() != true) return "fail 2"
if (null.foo<A>() != true) return "fail 3"
if (null.foo<A?>() != true) return "fail 4"
val a = A()
if (a.foo<Any>() != true) return "fail 5"
if (a.foo<Any?>() != true) return "fail 6"
if (a.foo<A>() != true) return "fail 7"
if (a.foo<A?>() != true) return "fail 8"
val b = B()
if (b.foo<A>() != false) return "fail 9"
if (b.foo<A?>() != false) return "fail 10"
return "OK"
}
@@ -0,0 +1,6 @@
package test
class A
class B
inline fun <reified T> Any?.foo() = this is T?
@@ -0,0 +1,24 @@
import test.*
fun box(): String {
if (null.foo<Any>() != false) return "fail 1"
if (null.foo<Any?>() != true) return "fail 2"
if (null.foo<A>() != false) return "fail 3"
if (null.foo<A?>() != true) return "fail 4"
val a = A()
if (a.foo<Any>() != true) return "fail 5"
if (a.foo<Any?>() != true) return "fail 6"
if (a.foo<A>() != true) return "fail 7"
if (a.foo<A?>() != true) return "fail 8"
val b = B()
if (b.foo<A>() != false) return "fail 9"
if (b.foo<A?>() != false) return "fail 10"
return "OK"
}
@@ -0,0 +1,6 @@
package test
class A
class B
inline fun <reified T> Any?.foo() = this is T
@@ -0,0 +1,11 @@
public class JavaClass {
public static String nullString() {
return null;
}
public static String nonnullString() {
return "OK";
}
}
@@ -0,0 +1,16 @@
fun box(): String {
val nullStr = JavaClass.nullString()
val nonnullStr = JavaClass.nonnullString()
if (nullStr.foo() != null) return "fail 1"
if (nonnullStr.foo() != nonnullStr) return "fail 2"
if (nullStr.fooN() != null) return "fail 3"
if (nonnullStr.fooN() != nonnullStr) return "fail 4"
return "OK"
}
inline fun <reified T> T.foo(): T = this as T
inline fun <reified T> T.fooN(): T? = this as T?
@@ -0,0 +1,11 @@
public class JavaClass {
public static String nullString() {
return null;
}
public static String nonnullString() {
return "OK";
}
}
@@ -0,0 +1,16 @@
fun box(): String {
val nullStr = JavaClass.nullString()
val nonnullStr = JavaClass.nonnullString()
if (nullStr.foo() != true) return "fail 1"
if (nonnullStr.foo() != true) return "fail 2"
if (nullStr.fooN() != true) return "fail 3"
if (nonnullStr.fooN() != true) return "fail 4"
return "OK"
}
inline fun <reified T> T.foo(): Boolean = this is T
inline fun <reified T> T.fooN(): Boolean = this is T?
@@ -0,0 +1,15 @@
inline fun <reified T> Any?.foo() = this as T
inline fun <reified Y> Any?.foo2() = foo<Y?>()
inline fun <reified Z> Any?.foo3() = foo2<Z>()
inline fun <reified X> Any?.foo4() = foo2<X?>()
inline fun <reified A> Any?.foo5() = foo<A>()
// 1 LDC "T"
// 1 LDC "Y\?"
// 1 LDC "Z\?"
// 1 LDC "X\?"
// 1 LDC "A"
@@ -0,0 +1,15 @@
inline fun <reified T> Any?.foo() = this as T?
inline fun <reified Y> Any?.foo2() = foo<Y?>()
inline fun <reified Z> Any?.foo3() = foo2<Z>()
inline fun <reified X> Any?.foo4() = foo2<X?>()
inline fun <reified A> Any?.foo5() = foo<A>()
// 1 LDC "T\?"
// 1 LDC "Y\?"
// 1 LDC "Z\?"
// 1 LDC "X\?"
// 1 LDC "A\?"
@@ -0,0 +1,15 @@
inline fun <reified T> Any?.foo() = this is T
inline fun <reified Y> Any?.foo2() = foo<Y?>()
inline fun <reified Z> Any?.foo3() = foo2<Z>()
inline fun <reified X> Any?.foo4() = foo2<X?>()
inline fun <reified A> Any?.foo5() = foo<A>()
// 1 LDC "T"
// 1 LDC "Y\?"
// 1 LDC "Z\?"
// 1 LDC "X\?"
// 1 LDC "A"
@@ -0,0 +1,15 @@
inline fun <reified T> Any?.foo() = this is T?
inline fun <reified Y> Any?.foo2() = foo<Y?>()
inline fun <reified Z> Any?.foo3() = foo2<Z>()
inline fun <reified X> Any?.foo4() = foo2<X?>()
inline fun <reified A> Any?.foo5() = foo<A>()
// 1 LDC "T\?"
// 1 LDC "Y\?"
// 1 LDC "Z\?"
// 1 LDC "X\?"
// 1 LDC "A\?"