|
| 1 | +trait Base[T, R] { |
| 2 | + def f(x: T): R |
| 3 | + def g(x: T): R |
| 4 | + def h(x: T): R = null.asInstanceOf[R] |
| 5 | +} |
| 6 | + |
| 7 | +trait Foo1[T] extends Base[T, String] { |
| 8 | + def f(x: T): String = null |
| 9 | + def g(x: T): String |
| 10 | +} |
| 11 | +trait Foo2[R] extends Base[String, R] { |
| 12 | + def f(x: String): R = { print(x.length) ; null.asInstanceOf[R] } |
| 13 | + def g(x: String): R |
| 14 | +} |
| 15 | +abstract class Foo3[T] extends Base[T, String] { |
| 16 | + def f(x: T): String = "" |
| 17 | + def g(x: T): String |
| 18 | +} |
| 19 | +abstract class Foo4[R] extends Base[String, R] { |
| 20 | + def f(x: String): R = { print(x.length) ; null.asInstanceOf[R] } |
| 21 | + def g(x: String): R |
| 22 | +} |
| 23 | + |
| 24 | +object Test { |
| 25 | + object bar1 extends Foo1[String] { def g(x: String): String = { print(x.length) ; "" } } |
| 26 | + object bar2 extends Foo2[String] { def g(x: String): String = { print(x.length) ; "" } } |
| 27 | + object bar3 extends Foo3[String] { def g(x: String): String = { print(x.length) ; "" } } |
| 28 | + object bar4 extends Foo4[String] { def g(x: String): String = { print(x.length) ; "" } } |
| 29 | + |
| 30 | + // Notice that in bar5, f and g require THREE bridges, because the final |
| 31 | + // implementation is (String)String, but: |
| 32 | + // |
| 33 | + // inherited abstract signatures: T(R), (T)String, and (String)R |
| 34 | + // which erase to: (Object)Object, (Object)String, and (String)Object |
| 35 | + // |
| 36 | + // each of which must be bridged to the actual (String)String implementation. |
| 37 | + // |
| 38 | + // public java.lang.String Test$bar5$.g(java.lang.String) |
| 39 | + // public java.lang.Object Test$bar5$.g(java.lang.String) <bridge> <synthetic> |
| 40 | + // public java.lang.Object Test$bar5$.g(java.lang.Object) <bridge> <synthetic> |
| 41 | + // public java.lang.String Test$bar5$.g(java.lang.Object) <bridge> <synthetic> |
| 42 | + object bar5 extends Foo1[String] with Foo2[String] { |
| 43 | + override def f(x: String): String = { print(x.length) ; x } |
| 44 | + def g(x: String): String = { print(x.length) ; x } |
| 45 | + } |
| 46 | + |
| 47 | + final def m1[T, R](x: Base[T, R], y: T) = { x.f(y) ; x.g(y) ; x.h(y) } |
| 48 | + final def m2[T](x: Base[T, String], y: T) = { x.f(y) ; x.g(y) ; x.h(y) } |
| 49 | + final def m3[R](x: Base[String, R]) = { x.f("") ; x.g("") ; x.h("") } |
| 50 | + final def m4(x: Base[String, String]) = { x.f("") ; x.g("") ; x.h("") } |
| 51 | + |
| 52 | + final def m11[T](x: Foo1[T], y: T) = { x.f(y) ; x.g(y) ; x.h(y) } |
| 53 | + final def m12(x: Foo1[String]) = { x.f("") ; x.g("") ; x.h("") } |
| 54 | + final def m21[T](x: Foo2[T], y: T) = { x.f("") ; x.g("") ; x.h("") } |
| 55 | + final def m22(x: Foo2[String]) = { x.f("") ; x.g("") ; x.h("") } |
| 56 | + final def m31[T](x: Foo3[T], y: T) = { x.f(y) ; x.g(y) ; x.h(y) } |
| 57 | + final def m32(x: Foo3[String]) = { x.f("") ; x.g("") ; x.h("") } |
| 58 | + final def m41[T](x: Foo4[T], y: T) = { x.f("") ; x.g("") ; x.h("") } |
| 59 | + final def m42(x: Foo4[String]) = { x.f("") ; x.g("") ; x.h("") } |
| 60 | + |
| 61 | + def go = { |
| 62 | + m1(bar1, "") ; m2(bar1, "") ; m3(bar1) ; m4(bar1) |
| 63 | + m1(bar2, "") ; m2(bar2, "") ; m3(bar2) ; m4(bar2) |
| 64 | + m1(bar3, "") ; m2(bar3, "") ; m3(bar3) ; m4(bar3) |
| 65 | + m1(bar4, "") ; m2(bar4, "") ; m3(bar4) ; m4(bar4) |
| 66 | + |
| 67 | + m11(bar1, "") ; m12(bar1) |
| 68 | + m21(bar2, "") ; m22(bar2) |
| 69 | + m31(bar3, "") ; m32(bar3) |
| 70 | + m41(bar4, "") ; m42(bar4) |
| 71 | + "" |
| 72 | + } |
| 73 | + |
| 74 | + def flagsString(m: java.lang.reflect.Method) = { |
| 75 | + val str = List( |
| 76 | + if (m.isBridge) "<bridge>" else "", |
| 77 | + if (m.isSynthetic) "<synthetic>" else "" |
| 78 | + ) filterNot (_ == "") mkString " " |
| 79 | + |
| 80 | + if (str == "") "" else " " + str |
| 81 | + // |
| 82 | + // val flags = scala.reflect.internal.ClassfileConstants.toScalaMethodFlags(m.getModifiers()) |
| 83 | + // scala.tools.nsc.symtab.Flags.flagsToString(flags) |
| 84 | + } |
| 85 | + |
| 86 | + def show(clazz: Class[_]): Unit = { |
| 87 | + print(clazz.toString + " {") |
| 88 | + clazz.getMethods.sortBy(x => (x.getName, x.isBridge, x.toString)) filter (_.getName.length == 1) foreach { m => |
| 89 | + print("\n " + m + flagsString(m)) |
| 90 | + if ("" + m != "" + m.toGenericString) { |
| 91 | + print("\n generic: " + m.toGenericString) |
| 92 | + } |
| 93 | + } |
| 94 | + println("\n}") |
| 95 | + println("") |
| 96 | + } |
| 97 | + def show(x: AnyRef): Unit = { show(x.getClass) } |
| 98 | + def show(x: String): Unit = { show(Class.forName(x)) } |
| 99 | + |
| 100 | + def main(args: Array[String]): Unit = { |
| 101 | + List(bar1, bar2, bar3, bar4, bar5) foreach show |
| 102 | + List("Foo1", "Foo2") foreach show |
| 103 | + println(go) |
| 104 | + } |
| 105 | +} |
0 commit comments