KT-2498 Bridge method is not generated for method when generic parameters are substituted in superclass

#KT-2498 Fixed

generateBridgeIfNeeded() now works as follows: for a given method, find
which declared methods does this method override via breadth-first search.
For each such declared method, generate a bridge if and only if its
signature is different. Keep different methods' signatures in a set to
avoid duplicated bridge signatures.
This commit is contained in:
Alexander Udalov
2012-07-30 16:11:38 +04:00
parent dad946b58d
commit cb9c18b7ad
23 changed files with 602 additions and 48 deletions
@@ -0,0 +1,15 @@
trait A<T> {
fun foo(t: T) = "A"
}
class Z : A<String>
fun box(): String {
val z = Z()
return when {
z.foo("") != "A" -> "Fail #1"
(z : A<String>).foo("") != "A" -> "Fail #2"
else -> "OK"
}
}
@@ -0,0 +1,23 @@
trait A<T, U> {
fun foo(t: T, u: U) = "A"
}
trait B<U> : A<String, U>
trait C<T> : A<T, Int>
class Z : B<Int>, C<String> {
override fun foo(t: String, u: Int) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("", 0) != "Z" -> "Fail #1"
(z : C<String>).foo("", 0) != "Z" -> "Fail #2"
(z : B<Int>).foo("", 0) != "Z" -> "Fail #3"
(z : A<String, Int>).foo("", 0) != "Z" -> "Fail #4"
else -> "OK"
}
}
@@ -0,0 +1,28 @@
open class A<T> {
open fun foo(t: T) = "A"
}
open class B<T> : A<T>()
open class C : B<String>() {
override fun foo(t: String) = "C"
}
open class D : C()
class Z : D() {
override fun foo(t: String) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("") != "Z" -> "Fail #1"
(z : D).foo("") != "Z" -> "Fail #2"
(z : C).foo("") != "Z" -> "Fail #3"
(z : B<String>).foo("") != "Z" -> "Fail #4"
(z : A<String>).foo("") != "Z" -> "Fail #5"
else -> "OK"
}
}
@@ -0,0 +1,23 @@
open class A<T, U, V> {
open fun foo(t: T, u: U, v: V) = "A"
}
open class B<T, V> : A<T, Int, V>()
open class C<V> : B<String, V>()
class Z : C<Double>() {
override fun foo(t: String, u: Int, v: Double) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("", 0, 0.0) != "Z" -> "Fail #1"
(z : C<Double>).foo("", 0, 0.0) != "Z" -> "Fail #2"
(z : B<String, Double>).foo("", 0, 0.0) != "Z" -> "Fail #3"
(z : A<String, Int, Double>).foo("", 0, 0.0) != "Z" -> "Fail #4"
else -> "OK"
}
}
@@ -0,0 +1,16 @@
trait A<T, U> {
fun foo(t: T, u: U) = "A"
}
class Z<T> : A<T, Int> {
override fun foo(t: T, u: Int) = "Z"
}
fun box(): String {
val z = Z<Int>()
return when {
z.foo(0, 0) != "Z" -> "Fail #1"
(z : A<Int, Int>).foo(0, 0) != "Z" -> "Fail #2"
else -> "OK"
}
}
@@ -0,0 +1,17 @@
open class A<T> {
open fun foo(t: T) = "A"
}
class Z : A<String>() {
override fun foo(t: String) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("") != "Z" -> "Fail #1"
(z : A<String>).foo("") != "Z" -> "Fail #2"
else -> "OK"
}
}
@@ -0,0 +1,20 @@
open enum class A<T> {
open fun foo(t: T) = "A"
}
enum class Z(val name: String) : A<String>() {
Z1 : Z("Z1")
Z2 : Z("Z2")
override fun foo(t: String) = name
}
fun box(): String {
return when {
Z.Z1.foo("") != "Z1" -> "Fail #1"
Z.Z2.foo("") != "Z2" -> "Fail #2"
(Z.Z1 : A<String>).foo("") != "Z1" -> "Fail #3"
(Z.Z2 : A<String>).foo("") != "Z2" -> "Fail #4"
else -> "OK"
}
}
@@ -0,0 +1,17 @@
open class A<T> {
open fun <U> foo(t: T, u: U) = "A"
}
class Z : A<String>() {
override fun <U> foo(t: String, u: U) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("", 0) != "Z" -> "Fail #1"
(z : A<String>).foo("", 0) != "Z" -> "Fail #2"
else -> "OK"
}
}
@@ -0,0 +1,21 @@
open class A<T> {
open fun foo(t: T) = "A"
}
object Z : A<String>() {
override fun foo(t: String) = "Z"
}
fun box(): String {
val z = object : A<String>() {
override fun foo(t: String) = "z"
}
return when {
Z.foo("") != "Z" -> "Fail #1"
z.foo("") != "z" -> "Fail #2"
(Z : A<String>).foo("") != "Z" -> "Fail #3"
(z : A<String>).foo("") != "z" -> "Fail #4"
else -> "OK"
}
}
@@ -0,0 +1,16 @@
open class A<T : Number>(val t: T) {
open fun foo(): T = t
}
class Z : A<Int>(17) {
override fun foo() = 239
}
fun box(): String {
val z = Z()
return when {
z.foo() != 239 -> "Fail #1"
(z : A<Int>).foo() != 239 -> "Fail #2"
else -> "OK"
}
}
@@ -0,0 +1,17 @@
open class A<T : Number> {
open fun foo(t: T) = "A"
}
class Z : A<Int>() {
override fun foo(t: Int) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo(0) != "Z" -> "Fail #1"
(z : A<Int>).foo(0) != "Z" -> "Fail #2"
else -> "OK"
}
}
@@ -0,0 +1,20 @@
open class A<T> {
open fun foo(t: T) = "A"
}
open class B : A<String>()
class Z : B() {
override fun foo(t: String) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("") != "Z" -> "Fail #1"
(z : B).foo("") != "Z" -> "Fail #2"
(z : A<String>).foo("") != "Z" -> "Fail #3"
else -> "OK"
}
}
@@ -0,0 +1,20 @@
abstract class A<T> {
abstract fun foo(t: T): String
}
abstract class B : A<String>()
class Z : B() {
override fun foo(t: String) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("") != "Z" -> "Fail #1"
(z : B).foo("") != "Z" -> "Fail #2"
(z : A<String>).foo("") != "Z" -> "Fail #3"
else -> "OK"
}
}
@@ -0,0 +1,19 @@
open class A<T : U, U> {
open fun foo(t: T, u: U) = "A"
}
open class B : A<Int, Number>()
class Z : B() {
override fun foo(t: Int, u: Number) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo(0, 0) != "Z" -> "Fail #1"
(z : B).foo(0, 0) != "Z" -> "Fail #2"
(z : A<Int, Number>).foo(0, 0) != "Z" -> "Fail #3"
else -> "OK"
}
}
@@ -0,0 +1,24 @@
open enum class A<T> {
open fun foo(t: T) = "A"
}
open enum class B : A<String>()
enum class Z(val name: String) : B() {
Z1 : Z("Z1")
Z2 : Z("Z2")
override fun foo(t: String) = name
}
fun box(): String {
return when {
Z.Z1.foo("") != "Z1" -> "Fail #1"
Z.Z2.foo("") != "Z2" -> "Fail #2"
(Z.Z1 : B).foo("") != "Z1" -> "Fail #3"
(Z.Z2 : B).foo("") != "Z2" -> "Fail #4"
(Z.Z1 : A<String>).foo("") != "Z1" -> "Fail #5"
(Z.Z2 : A<String>).foo("") != "Z2" -> "Fail #6"
else -> "OK"
}
}
@@ -0,0 +1,20 @@
open class A<T> {
open fun <U> foo(t: T, u: U) = "A"
}
open class B : A<String>()
class Z : B() {
override fun <U> foo(t: String, u: U) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("", 0) != "Z" -> "Fail #1"
(z : B).foo("", 0) != "Z" -> "Fail #2"
(z : A<String>).foo("", 0) != "Z" -> "Fail #3"
else -> "OK"
}
}
@@ -0,0 +1,25 @@
open class A<T> {
open fun foo(t: T) = "A"
}
open class B : A<String>()
object Z : B() {
override fun foo(t: String) = "Z"
}
fun box(): String {
val o = object : B() {
override fun foo(t: String) = "o"
}
return when {
Z.foo("") != "Z" -> "Fail #1"
o.foo("") != "o" -> "Fail #2"
(Z : B).foo("") != "Z" -> "Fail #3"
(o : B).foo("") != "o" -> "Fail #4"
(Z : A<String>).foo("") != "Z" -> "Fail #5"
(o : A<String>).foo("") != "o" -> "Fail #6"
else -> "OK"
}
}
@@ -0,0 +1,20 @@
open class A<T : Number> {
open fun foo(t: T) = "A"
}
open class B : A<Int>()
class Z : B() {
override fun foo(t: Int) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo(0) != "Z" -> "Fail #1"
(z : B).foo(0) != "Z" -> "Fail #2"
(z : A<Int>).foo(0) != "Z" -> "Fail #3"
else -> "OK"
}
}
@@ -0,0 +1,22 @@
trait A<T> {
fun foo(t: T, u: Int) = "A"
}
trait B<T, U> {
fun foo(t: T, u: U) = "B"
}
class Z : A<String>, B<String, Int> {
override fun foo(t: String, u: Int) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo("", 0) != "Z" -> "Fail #1"
(z : A<String>).foo("", 0) != "Z" -> "Fail #2"
(z : B<String, Int>).foo("", 0) != "Z" -> "Fail #3"
else -> "OK"
}
}
@@ -0,0 +1,22 @@
trait A<T> {
fun foo(t: T) = "A"
}
trait B<T> {
fun foo(t: T) = "B"
}
class Z : A<Int>, B<Int> {
override fun foo(t: Int) = "Z"
}
fun box(): String {
val z = Z()
return when {
z.foo(0) != "Z" -> "Fail #1"
(z : A<Int>).foo(0) != "Z" -> "Fail #2"
(z : B<Int>).foo(0) != "Z" -> "Fail #3"
else -> "OK"
}
}
@@ -0,0 +1,19 @@
import java.util.LinkedList
open class BaseStringList: LinkedList<String>() {
}
class StringList: BaseStringList() {
public override fun get(index: Int): String {
return "StringList.get()"
}
}
fun box(): String {
val myStringList = StringList()
myStringList.add("first element")
if (myStringList.get(0) != "StringList.get()") return "Fail #1"
if ((myStringList: BaseStringList).get(0) != "StringList.get()") return "Fail #2"
if ((myStringList: LinkedList<String>).get(0) != "StringList.get()") return "Fail #3"
return "OK"
}