forked from scala/scala3
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is the same scheme I proposed in scala/scala#7843 which sidesteps all the issues regarding mixin forwarders and generic signatures, see the discussion in that PR for more information. Tests imported from scalac, some of the comments in them might not be correct for Dotty anymore.
- Loading branch information
Showing
20 changed files
with
284 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
case class Foo(x: Int) | ||
|
||
trait A[X] { | ||
def concat[Dummy](suffix: Int): Dummy = ??? | ||
} | ||
|
||
class Bar extends A[Foo] { | ||
def concat(suffix: Int): Foo = Foo(0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
public class Test { | ||
public static void main(String[] args) { | ||
Bar bar = new Bar(); | ||
Foo x = bar.concat(0); | ||
System.out.println(x); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
class Test$bar1$ { | ||
public java.lang.Object Test$bar1$.f(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.String Test$bar1$.f(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.String Test$bar1$.g(java.lang.String) | ||
public java.lang.Object Test$bar1$.g(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.String Test$bar1$.g(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.Object Test$bar1$.h(java.lang.Object) <bridge> <synthetic> | ||
} | ||
|
||
class Test$bar2$ { | ||
public java.lang.Object Test$bar2$.f(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.Object Test$bar2$.f(java.lang.String) <bridge> <synthetic> | ||
public java.lang.String Test$bar2$.g(java.lang.String) | ||
public java.lang.Object Test$bar2$.g(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.Object Test$bar2$.g(java.lang.String) <bridge> <synthetic> | ||
public java.lang.Object Test$bar2$.h(java.lang.Object) <bridge> <synthetic> | ||
} | ||
|
||
class Test$bar3$ { | ||
public java.lang.String Foo3.f(java.lang.Object) | ||
generic: public java.lang.String Foo3.f(T) | ||
public java.lang.Object Foo3.f(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.String Test$bar3$.g(java.lang.String) | ||
public java.lang.Object Test$bar3$.g(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.String Test$bar3$.g(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.Object Foo3.h(java.lang.Object) <bridge> <synthetic> | ||
} | ||
|
||
class Test$bar4$ { | ||
public java.lang.Object Foo4.f(java.lang.String) | ||
generic: public R Foo4.f(java.lang.String) | ||
public java.lang.Object Foo4.f(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.String Test$bar4$.g(java.lang.String) | ||
public java.lang.Object Test$bar4$.g(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.Object Test$bar4$.g(java.lang.String) <bridge> <synthetic> | ||
public java.lang.Object Foo4.h(java.lang.Object) <bridge> <synthetic> | ||
} | ||
|
||
class Test$bar5$ { | ||
public java.lang.String Test$bar5$.f(java.lang.String) | ||
public java.lang.Object Test$bar5$.f(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.Object Test$bar5$.f(java.lang.String) <bridge> <synthetic> | ||
public java.lang.String Test$bar5$.f(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.String Test$bar5$.g(java.lang.String) | ||
public java.lang.Object Test$bar5$.g(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.Object Test$bar5$.g(java.lang.String) <bridge> <synthetic> | ||
public java.lang.String Test$bar5$.g(java.lang.Object) <bridge> <synthetic> | ||
public java.lang.Object Test$bar5$.h(java.lang.Object) <bridge> <synthetic> | ||
} | ||
|
||
interface Foo1 { | ||
public abstract java.lang.Object Base.f(java.lang.Object) | ||
generic: public abstract R Base.f(T) | ||
public default java.lang.String Foo1.f(java.lang.Object) | ||
generic: public default java.lang.String Foo1.f(T) | ||
public abstract java.lang.Object Base.g(java.lang.Object) | ||
generic: public abstract R Base.g(T) | ||
public abstract java.lang.String Foo1.g(java.lang.Object) | ||
generic: public abstract java.lang.String Foo1.g(T) | ||
public default java.lang.Object Base.h(java.lang.Object) | ||
generic: public default R Base.h(T) | ||
} | ||
|
||
interface Foo2 { | ||
public abstract java.lang.Object Base.f(java.lang.Object) | ||
generic: public abstract R Base.f(T) | ||
public default java.lang.Object Foo2.f(java.lang.String) | ||
generic: public default R Foo2.f(java.lang.String) | ||
public abstract java.lang.Object Base.g(java.lang.Object) | ||
generic: public abstract R Base.g(T) | ||
public abstract java.lang.Object Foo2.g(java.lang.String) | ||
generic: public abstract R Foo2.g(java.lang.String) | ||
public default java.lang.Object Base.h(java.lang.Object) | ||
generic: public default R Base.h(T) | ||
} | ||
|
||
000000000000000000000000000000000000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
trait Base[T, R] { | ||
def f(x: T): R | ||
def g(x: T): R | ||
def h(x: T): R = null.asInstanceOf[R] | ||
} | ||
|
||
trait Foo1[T] extends Base[T, String] { | ||
def f(x: T): String = null | ||
def g(x: T): String | ||
} | ||
trait Foo2[R] extends Base[String, R] { | ||
def f(x: String): R = { print(x.length) ; null.asInstanceOf[R] } | ||
def g(x: String): R | ||
} | ||
abstract class Foo3[T] extends Base[T, String] { | ||
def f(x: T): String = "" | ||
def g(x: T): String | ||
} | ||
abstract class Foo4[R] extends Base[String, R] { | ||
def f(x: String): R = { print(x.length) ; null.asInstanceOf[R] } | ||
def g(x: String): R | ||
} | ||
|
||
object Test { | ||
object bar1 extends Foo1[String] { def g(x: String): String = { print(x.length) ; "" } } | ||
object bar2 extends Foo2[String] { def g(x: String): String = { print(x.length) ; "" } } | ||
object bar3 extends Foo3[String] { def g(x: String): String = { print(x.length) ; "" } } | ||
object bar4 extends Foo4[String] { def g(x: String): String = { print(x.length) ; "" } } | ||
|
||
// Notice that in bar5, f and g require THREE bridges, because the final | ||
// implementation is (String)String, but: | ||
// | ||
// inherited abstract signatures: T(R), (T)String, and (String)R | ||
// which erase to: (Object)Object, (Object)String, and (String)Object | ||
// | ||
// each of which must be bridged to the actual (String)String implementation. | ||
// | ||
// public java.lang.String Test$bar5$.g(java.lang.String) | ||
// public java.lang.Object Test$bar5$.g(java.lang.String) <bridge> <synthetic> | ||
// public java.lang.Object Test$bar5$.g(java.lang.Object) <bridge> <synthetic> | ||
// public java.lang.String Test$bar5$.g(java.lang.Object) <bridge> <synthetic> | ||
object bar5 extends Foo1[String] with Foo2[String] { | ||
override def f(x: String): String = { print(x.length) ; x } | ||
def g(x: String): String = { print(x.length) ; x } | ||
} | ||
|
||
final def m1[T, R](x: Base[T, R], y: T) = { x.f(y) ; x.g(y) ; x.h(y) } | ||
final def m2[T](x: Base[T, String], y: T) = { x.f(y) ; x.g(y) ; x.h(y) } | ||
final def m3[R](x: Base[String, R]) = { x.f("") ; x.g("") ; x.h("") } | ||
final def m4(x: Base[String, String]) = { x.f("") ; x.g("") ; x.h("") } | ||
|
||
final def m11[T](x: Foo1[T], y: T) = { x.f(y) ; x.g(y) ; x.h(y) } | ||
final def m12(x: Foo1[String]) = { x.f("") ; x.g("") ; x.h("") } | ||
final def m21[T](x: Foo2[T], y: T) = { x.f("") ; x.g("") ; x.h("") } | ||
final def m22(x: Foo2[String]) = { x.f("") ; x.g("") ; x.h("") } | ||
final def m31[T](x: Foo3[T], y: T) = { x.f(y) ; x.g(y) ; x.h(y) } | ||
final def m32(x: Foo3[String]) = { x.f("") ; x.g("") ; x.h("") } | ||
final def m41[T](x: Foo4[T], y: T) = { x.f("") ; x.g("") ; x.h("") } | ||
final def m42(x: Foo4[String]) = { x.f("") ; x.g("") ; x.h("") } | ||
|
||
def go = { | ||
m1(bar1, "") ; m2(bar1, "") ; m3(bar1) ; m4(bar1) | ||
m1(bar2, "") ; m2(bar2, "") ; m3(bar2) ; m4(bar2) | ||
m1(bar3, "") ; m2(bar3, "") ; m3(bar3) ; m4(bar3) | ||
m1(bar4, "") ; m2(bar4, "") ; m3(bar4) ; m4(bar4) | ||
|
||
m11(bar1, "") ; m12(bar1) | ||
m21(bar2, "") ; m22(bar2) | ||
m31(bar3, "") ; m32(bar3) | ||
m41(bar4, "") ; m42(bar4) | ||
"" | ||
} | ||
|
||
def flagsString(m: java.lang.reflect.Method) = { | ||
val str = List( | ||
if (m.isBridge) "<bridge>" else "", | ||
if (m.isSynthetic) "<synthetic>" else "" | ||
) filterNot (_ == "") mkString " " | ||
|
||
if (str == "") "" else " " + str | ||
// | ||
// val flags = scala.reflect.internal.ClassfileConstants.toScalaMethodFlags(m.getModifiers()) | ||
// scala.tools.nsc.symtab.Flags.flagsToString(flags) | ||
} | ||
|
||
def show(clazz: Class[_]): Unit = { | ||
print(clazz.toString + " {") | ||
clazz.getMethods.sortBy(x => (x.getName, x.isBridge, x.toString)) filter (_.getName.length == 1) foreach { m => | ||
print("\n " + m + flagsString(m)) | ||
if ("" + m != "" + m.toGenericString) { | ||
print("\n generic: " + m.toGenericString) | ||
} | ||
} | ||
println("\n}") | ||
println("") | ||
} | ||
def show(x: AnyRef): Unit = { show(x.getClass) } | ||
def show(x: String): Unit = { show(Class.forName(x)) } | ||
|
||
def main(args: Array[String]): Unit = { | ||
List(bar1, bar2, bar3, bar4, bar5) foreach show | ||
List("Foo1", "Foo2") foreach show | ||
println(go) | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,6 @@ | ||
import scala.collection.immutable.Nil; | ||
import scala.collection.immutable.List; | ||
import scala.collection.Traversable; | ||
|
||
public class Test { | ||
public static void main(String[] args) { | ||
C<String> c = new C<String>(); | ||
// TODO add a bridge during mixin so we can expose | ||
// sharper generic signature for `tail`. | ||
/*Traversable<String>*/ Object ls = c.tail(); | ||
scala.collection.Iterable<String> ls = c.tail(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,10 @@ | ||
|
||
public class Test { | ||
public static void main(String[] args) { | ||
// To get better types here, we would need to | ||
// add bridge during mixin so we can expose | ||
// a generic return type of Traversable<A>, because the erasure | ||
// of this (Traversable) differs from the erasure of the mixed | ||
// method (erasure(Repr) = Object) | ||
public static void main(String[] args) { | ||
AbstractTrav<String> lsSharp1 = new C1().tail(); | ||
|
||
Object lsSharp = O.tail(); | ||
// Object is the result type for the static forwarder (might be because of #11305) | ||
Object lsSharp2 = O.tail(); | ||
|
||
Object lsSharp2 = new C<String>().tail(); | ||
} | ||
AbstractTrav<String> lsSharp3 = new C2<String>().tail(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,8 @@ | ||
class Mix extends Foo with Bar { f; } | ||
class Mix___eFoo_I_wBar__f extends Foo_I_ with Bar__f { f; } | ||
trait T | ||
abstract class Foo { | ||
class I extends T | ||
def f: I | ||
f | ||
} | ||
trait Bar { | ||
type I >: Null <: T | ||
def f: I = null | ||
f | ||
def gobble: I = null | ||
} | ||
abstract class Foo_I_ { class I extends T ; def f: I ; f; } | ||
trait Bar__f { type I>:Null<:T; def f: I = {null}; f; def gobble: I = {null}} | ||
|
||
object Test extends dotty.runtime.LegacyApp { | ||
new Mix | ||
object Test extends App { | ||
new Mix___eFoo_I_wBar__f | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
public Category C.category() | ||
public Category C.category1() | ||
public default Category<F> M1.category() | ||
public default Category<scala.Tuple2> M1.category1() | ||
public default Category<F> M2.category() | ||
public default Category<scala.Tuple2> M2.category1() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import scala.language.higherKinds | ||
|
||
class Category[M[_, _]] | ||
|
||
trait M1[F] { | ||
type X[a, b] = F | ||
def category: Category[X] = null | ||
def category1: Category[Tuple2] = null | ||
} | ||
|
||
// The second trait is needed to make sure there's a forwarder generated in C. | ||
// otherwise the trait methods are just the inherited default methods from M1. | ||
trait M2[F] { self: M1[F] => | ||
override def category: Category[X] = null | ||
override def category1: Category[Tuple2] = null | ||
} | ||
|
||
abstract class C extends M1[Float] with M2[Float] | ||
|
||
object Test { | ||
def t(c: Class[_]) = { | ||
val ms = c.getMethods.filter(_.getName.startsWith("category")) | ||
println(ms.map(_.toGenericString).sorted.mkString("\n")) | ||
} | ||
def main(args: Array[String]): Unit = { | ||
t(classOf[C]) | ||
t(classOf[M1[_]]) | ||
t(classOf[M2[_]]) | ||
} | ||
} |
Oops, something went wrong.