Support bridges in interfaces for default methods

This commit is contained in:
Mikhail Bogdanov
2020-03-27 18:21:38 +01:00
parent 93b915c77a
commit a3f930d2e4
18 changed files with 790 additions and 5 deletions
@@ -0,0 +1,25 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface Test<T> {
fun test(p: T): T {
return p
}
}
class TestClass : Test<String> {
override fun test(p: String): String {
return p + "K"
}
}
fun <T> execute(t: Test<T>, p: T): T {
return t.test(p)
}
fun box(): String {
return execute(TestClass(), "O")
}
@@ -0,0 +1,28 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface Test<T> {
fun test(p: T): T {
return p
}
}
interface Test2: Test<String> {
override fun test(p: String): String {
return p + "K"
}
}
class TestClass : Test2 {
}
fun <T> execute(t: Test<T>, p: T): T {
return t.test(p)
}
fun box(): String {
return execute(TestClass(), "O")
}
@@ -0,0 +1,56 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
// FULL_JDK
interface Test<T> {
fun test(p: T): T {
return null!!
}
}
interface Test2: Test<String> {
override fun test(p: String): String {
return p
}
}
class TestClass : Test2
fun box(): String {
checkMethodExists(Test2::class.java, "test", Any::class.java)
checkMethodExists(Test2::class.java, "test", String::class.java)
checkNoMethod(TestClass::class.java, "test", String::class.java)
checkNoMethod(TestClass::class.java, "test", Any::class.java)
val test2DefaultImpls = java.lang.Class.forName("Test2\$DefaultImpls")
checkMethodExists(test2DefaultImpls, "test", Test2::class.java, String::class.java)
checkNoMethod(test2DefaultImpls, "test", Test2::class.java, Any::class.java)
return "OK"
}
fun checkNoMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
try {
clazz.getDeclaredMethod(name, *parameterTypes)
}
catch (e: NoSuchMethodException) {
return
}
throw AssertionError("fail: method $name was found in " + clazz)
}
fun checkMethodExists(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
try {
clazz.getDeclaredMethod(name, *parameterTypes)
return
}
catch (e: NoSuchMethodException) {
throw AssertionError("fail: method $name was not found in " + clazz, e)
}
}
@@ -0,0 +1,33 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface Test<T> {
var test: T
get() = null!!
set(value) {
null!!
}
}
var result = "fail"
interface Test2 : Test<String> {
override var test: String
get() = result
set(value) {
result = value
}
}
class TestClass : Test2
fun <T> execute(t: Test<T>, p: T): T {
t.test = p
return t.test
}
fun box(): String {
return execute(TestClass(), "OK")
}
@@ -0,0 +1,63 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
// FULL_JDK
interface Test<T> {
var T.test: T
get() = null!!
set(value) {
null!!
}
}
interface Test2 : Test<String> {
override var String.test: String
get() = ""
set(value) {}
}
class TestClass : Test2
fun box(): String {
checkMethodExists(Test2::class.java, "getTest", String::class.java)
checkMethodExists(Test2::class.java, "getTest", Any::class.java)
checkMethodExists(Test2::class.java, "setTest", Any::class.java, Any::class.java)
checkMethodExists(Test2::class.java, "setTest", String::class.java, String::class.java)
checkNoMethod(TestClass::class.java, "getTest", String::class.java)
checkNoMethod(TestClass::class.java, "getTest", Any::class.java)
checkNoMethod(TestClass::class.java, "setTest", Any::class.java, Any::class.java)
checkNoMethod(TestClass::class.java, "setTest", String::class.java, String::class.java)
val test2DefaultImpls = java.lang.Class.forName("Test2\$DefaultImpls")
checkMethodExists(test2DefaultImpls, "getTest", Test2::class.java, String::class.java)
checkNoMethod(test2DefaultImpls, "getTest", Test2::class.java, Any::class.java)
checkNoMethod(test2DefaultImpls, "setTest", Test2::class.java, Any::class.java, Any::class.java)
checkMethodExists(test2DefaultImpls, "setTest", Test2::class.java, String::class.java, String::class.java)
return "OK"
}
fun checkNoMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
try {
clazz.getDeclaredMethod(name, *parameterTypes)
}
catch (e: NoSuchMethodException) {
return
}
throw AssertionError("fail: method $name was found in " + clazz)
}
fun checkMethodExists(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
try {
clazz.getDeclaredMethod(name, *parameterTypes)
return
}
catch (e: NoSuchMethodException) {
throw AssertionError("fail: method $name was not found in " + clazz, e)
}
}
@@ -0,0 +1,61 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
// FULL_JDK
// FILE: Test.java
public interface Test<T> {
default T test(T p) {
return null;
}
}
// FILE: kotlin.kt
interface Test2: Test<String> {
override fun test(p: String): String {
return p
}
fun forDefaultImpls() {}
}
class TestClass : Test2
fun box(): String {
checkMethodExists(Test2::class.java, "test", String::class.java)
checkMethodExists(Test2::class.java, "test", Any::class.java)
checkNoMethod(TestClass::class.java, "test", String::class.java)
checkNoMethod(TestClass::class.java, "test", Any::class.java)
val test2DefaultImpls = java.lang.Class.forName("Test2\$DefaultImpls")
checkNoMethod(test2DefaultImpls, "test", Any::class.java)
checkNoMethod(test2DefaultImpls, "test", String::class.java)
return "OK"
}
fun checkNoMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
try {
clazz.getDeclaredMethod(name, *parameterTypes)
}
catch (e: NoSuchMethodException) {
return
}
throw AssertionError("fail: method $name was found in " + clazz)
}
fun checkMethodExists(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
try {
clazz.getDeclaredMethod(name, *parameterTypes)
return
}
catch (e: NoSuchMethodException) {
throw AssertionError("fail: method $name was not found in " + clazz, e)
}
}