Add some tests on adapted references with varargs and reflection

Also rename "varargAndDefaults" test directory to "adaptedReferences"
This commit is contained in:
Alexander Udalov
2020-04-06 18:44:36 +02:00
parent 66995fe1a5
commit fa879e667f
27 changed files with 718 additions and 674 deletions
@@ -0,0 +1,17 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(s: String = "kotlin", vararg t: String): Boolean {
if (s != "kotlin") throw AssertionError(s)
if (t.size != 0) throw AssertionError(t.size.toString())
return true
}
fun bar(f: () -> Unit) {
f()
}
fun box(): String {
bar(::foo)
return "OK"
}
@@ -0,0 +1,48 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.test.assertEquals
class C(val expected: Int) {
fun memberVararg(i: Int, vararg s: String) {
assertEquals(expected, i)
assertEquals(0, s.size)
}
fun memberDefault(i: Int, s: String = "") {
assertEquals(expected, i)
assertEquals("", s)
}
fun memberBoth(i: Int, s: String = "", vararg t: String) {
assertEquals(expected, i)
assertEquals("", s)
assertEquals(0, t.size)
}
}
fun C.extensionVararg(i: Int, vararg s: String) {
memberVararg(i, *s)
}
fun C.extensionDefault(i: Int, s: String = "") {
memberDefault(i, s)
}
fun C.extensionBoth(i: Int, s: String = "", vararg t: String) {
memberBoth(i, s, *t)
}
fun test(f: (Int) -> Unit, p: Int) = f(p)
fun box(): String {
test(C(42)::memberVararg, 42)
test(C(42)::memberDefault, 42)
test(C(42)::memberBoth, 42)
test(C(42)::extensionVararg, 42)
test(C(42)::extensionDefault, 42)
test(C(42)::extensionBoth, 42)
return "OK"
}
@@ -0,0 +1,11 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(vararg a: String, result: String = "OK"): String =
if (a.size == 0) result else "Fail"
fun call(f: () -> String): String = f()
fun box(): String {
return call(::foo)
}
@@ -0,0 +1,9 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
fun foo(x: String, y: Char = 'K'): String = x + y
fun <T, U> call(f: (T) -> U, x: T): U = f(x)
fun box(): String {
return call(::foo, "O")
}
@@ -0,0 +1,11 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(x: String = "O", vararg y: String): String =
if (y.size == 0) x + "K" else "Fail"
fun call(f: () -> String): String = f()
fun box(): String {
return call(::foo)
}
@@ -0,0 +1,11 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
inline fun foo(mkString: () -> String): String =
mkString()
fun bar (xs: CharArray = charArrayOf('O','K')) =
String(xs)
fun box(): String = foo(::bar)
@@ -0,0 +1,13 @@
// !LANGUAGE: +NewInference
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
inline fun foo(mkString: (Char, Char) -> String): String =
mkString('O','K')
fun bar (vararg xs: Char) =
String(xs)
fun box(): String = foo(::bar)
// -> { a, b -> bar(a, b) }
@@ -0,0 +1,9 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(vararg l: Long, s: String = "OK"): String =
if (l.size == 0) s else "Fail"
inline fun bar(f: () -> String): String = f()
fun box(): String = bar(::foo)
@@ -0,0 +1,13 @@
// !LANGUAGE: +NewInference
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
inline fun foo(x: (Int, Int) -> Int): Int =
x(120,3)
fun bar(vararg x: Int): Int =
x.sum()
fun box(): String =
if (foo(::bar) == 123) "OK" else "FAIL"
@@ -0,0 +1,34 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
class Outer(val o: String) {
inner class Inner1(val i: Int, vararg v: String) {
val result = "I1" + o + i + if (v.size == 0) "E" else v[0]
}
inner class Inner2(val i: Int, vararg v: String = arrayOf("A")) {
val result = "I2" + o + i + v[0]
}
}
fun <T> use0(f: (Int) -> T) = f(11)
fun <T> use1(f: (Int, String) -> T) = f(12, "B")
fun box(): String {
val oouter = Outer("O")
val r1 = use0(oouter::Inner1).result
if (r1 != "I1O11E") return "Fail1: $r1"
val r2 = use1(oouter::Inner1).result
if (r2 != "I1O12B") return "Fail2: $r2"
val r3 = use0(oouter::Inner2).result
if (r3 != "I2O11A") return "Fail3: $r3"
val r4 = use1(oouter::Inner2).result
if (r4 != "I2O12B") return "Fail4: $r4"
return "OK"
}
@@ -0,0 +1,20 @@
// !LANGUAGE: +NewInference
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(
f: (
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int
) -> String
) = f(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40
)
fun bar(first: Int, vararg args: Int) = if (args.size == 39) "OK" else "Fail: ${args.size}"
fun box(): String = foo(::bar)
@@ -0,0 +1,31 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
fun call0(f: (String) -> String, x: String): String = f(x)
fun call1(f: (String, String) -> String, x: String, y: String): String = f(x, y)
fun call2(f: (String, String, String) -> String, x: String, y: String, z: String): String = f(x, y, z)
fun box(): String {
var s = "1"
fun foo(x: String, y: String = "5", z: String = "4"): String = s + x + y + z
val r = call1(::foo, "2", "3")
if (r != "1234") return "FAIL $r"
fun bar(x: String, vararg y: CharSequence = arrayOf("2")): String = s + x + y.size + y[0]
s = "5"
val r0 = call0(::bar, "3")
if (r0 != "5312") return "FAIL1 $r0"
s = "6"
val r2 = call1(::bar, "2", "5")
if (r2 != "6215") return "FAIL2 $r2"
s = "7"
val r3 = call2(::bar, "8", "9", "10")
if (r3 != "7829") return "FAIL3 $r3"
return "OK"
}
@@ -0,0 +1,28 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.test.assertEquals
object E : Exception()
fun foo(
a: String = "fail",
b: Int,
c: Double = 3.14,
vararg d: String,
e: Throwable = E
) {
assertEquals("ok", a)
assertEquals(42, b)
assertEquals(3.14, c)
assertEquals(0, d.size)
assertEquals(E, e)
}
fun bar(f: (String, Int) -> Unit) = f("ok", 42)
fun box(): String {
bar(::foo)
return "OK"
}
@@ -0,0 +1,39 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.reflect.KCallable
private fun check(label: String, fn: Any) {
if (fn is KCallable<*>) {
throw AssertionError("$label is KCallable, ${fn::class.java.simpleName}")
}
}
fun checkUnit(label: String, fn: () -> Unit) = check(label, fn)
fun checkAny(label: String, fn: () -> Any) = check(label, fn)
fun checkOneElementForVararg(label: String, fn: (Int) -> Unit) = check(label, fn)
fun withDefaults(a: Int = 1, b: Int = 2) {}
fun withVarargs(vararg xs: Int) {}
fun withCoercion() = 1
class CWithDefaults(x: Int = 1, y: Int = 2)
class CWithVarargs(vararg xs: Int)
fun box(): String {
checkUnit("::withDefaults", ::withDefaults)
checkUnit("::withVarargs", ::withVarargs)
checkUnit("::withCoercion", ::withCoercion)
checkAny("::CWithDefaults", ::CWithDefaults)
checkAny("::CWithVarargs", ::CWithVarargs)
checkUnit("::CWithDefaults", ::CWithDefaults)
checkUnit("::CWithVarargs", ::CWithVarargs)
checkOneElementForVararg("::withVarargs", ::withVarargs)
checkOneElementForVararg("::CWithVarargs", ::CWithVarargs)
return "OK"
}
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
import kotlin.reflect.KCallable
private fun check(label: String, fn: Any) {
if (fn !is KCallable<*>) {
throw AssertionError("$label is not KCallable, ${fn::class.java.simpleName}")
}
}
fun checkVarargAsArray(label: String, fn: (IntArray) -> C) = check(label, fn)
fun withVarargs(vararg xs: Int): C = C(*xs)
class C(vararg xs: Int)
fun box(): String {
checkVarargAsArray("::withVarargs", ::withVarargs)
checkVarargAsArray("::C", ::C)
return "OK"
}
@@ -0,0 +1,9 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
fun foo(x: String, y: String = "K"): String = x + y
fun call(f: (String) -> String, x: String): String = f(x)
fun box(): String {
return call(::foo, "O")
}
@@ -0,0 +1,11 @@
// !LANGUAGE: +NewInference
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(x: String, vararg y: String): String =
if (y.size == 0) x + "K" else "Fail"
fun call(f: (String) -> String, x: String): String = f(x)
fun box(): String {
return call(::foo, "O")
}
@@ -0,0 +1,49 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
import kotlin.test.assertEquals
class C(val expected: Int) {
fun memberVararg(i: Int, vararg s: String) {
assertEquals(expected, i)
assertEquals(0, s.size)
}
fun memberDefault(i: Int, s: String = "") {
assertEquals(expected, i)
assertEquals("", s)
}
fun memberBoth(i: Int, s: String = "", vararg t: String) {
assertEquals(expected, i)
assertEquals("", s)
assertEquals(0, t.size)
}
}
fun C.extensionVararg(i: Int, vararg s: String) {
memberVararg(i, *s)
}
fun C.extensionDefault(i: Int, s: String = "") {
memberDefault(i, s)
}
fun C.extensionBoth(i: Int, s: String = "", vararg t: String) {
memberBoth(i, s, *t)
}
fun test(f: C.(Int) -> Unit, p: Int) = C(p).f(p)
fun box(): String {
test(C::memberVararg, 43)
test(C::memberDefault, 43)
test(C::memberBoth, 43)
test(C::extensionVararg, 43)
test(C::extensionDefault, 43)
test(C::extensionBoth, 43)
return "OK"
}
@@ -0,0 +1,9 @@
// KT-25514 Support usage of function reference with vararg where function of array is expected in new inference
fun foo(x: Int, vararg y: String): String = y[0]
fun useArray(f: (Int, Array<String>) -> String): String = f(1, Array(1) { "OK" })
fun box(): String {
return useArray(::foo)
}
@@ -0,0 +1,28 @@
// IGNORE_BACKEND_FIR: JVM_IR
// !LANGUAGE: +NewInference
fun sum(vararg args: Int): Int {
var result = 0
for (arg in args)
result += arg
return result
}
fun nsum(vararg args: Number) = sum(*IntArray(args.size) { args[it].toInt() })
fun usePlainArgs(fn: (Int, Int) -> Int) = fn(1, 1)
fun usePrimitiveArray(fn: (IntArray) -> Int) = fn(intArrayOf(1, 1, 1))
fun useArray(fn: (Array<Int>) -> Int) = fn(arrayOf(1, 1, 1, 1))
fun box(): String {
var result = usePlainArgs(::sum)
if (result != 2)
return "Fail: plain args $result != 2"
result = usePrimitiveArray(::sum)
if (result != 3)
return "Fail: primitive array $result != 3"
result = useArray(::nsum)
if (result != 4)
return "Fail: reference array $result != 4"
return "OK"
}
@@ -0,0 +1,15 @@
// !LANGUAGE: +NewInference +FunctionReferenceWithDefaultValueAsOtherType
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(x: Int, s: Int, vararg y: CharSequence = arrayOf("Aaa")): String =
if (y.size == s && y[0].length == x) "OK" else "Fail"
fun use0(f: (Int, Int) -> String): String = f(3, 1)
fun use1(f: (Int, Int, String) -> String): String = f(5, 1, "Bbbbb")
fun use2(f: (Int, Int, String, String) -> String): String = f(5, 2, "Bbbbb", "Ccccc")
fun box(): String {
if (use0(::foo) != "OK") return "Fail0"
if (use1(::foo) != "OK") return "Fail1"
return use2(::foo)
}