diff options
author | Adriaan Moors <adriaan@lightbend.com> | 2017-01-10 16:33:37 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-10 16:33:37 -0800 |
commit | a5d38ea33430e144d05e7486791f70e144c5b602 (patch) | |
tree | 18b1458795b529dd1331b84231e8a8add0946fa3 /test | |
parent | 36967321c7a8a99cab2f9f1c4c0c46f09d3d34a6 (diff) | |
parent | 359b0bce8ec9bced0ca6fbb3865e9b3a6bcb30b4 (diff) | |
download | scala-a5d38ea33430e144d05e7486791f70e144c5b602.tar.gz scala-a5d38ea33430e144d05e7486791f70e144c5b602.tar.bz2 scala-a5d38ea33430e144d05e7486791f70e144c5b602.zip |
Merge pull request #5630 from adriaanm/rebase-5557
[backport] SI-10071 SI-8786 varargs methods
Diffstat (limited to 'test')
-rw-r--r-- | test/files/jvm/t8786-sig.scala | 126 | ||||
-rw-r--r-- | test/files/jvm/t8786/A_1.scala | 3 | ||||
-rw-r--r-- | test/files/jvm/t8786/B_2.java | 22 | ||||
-rw-r--r-- | test/files/jvm/t8786/Test_2.scala | 3 | ||||
-rw-r--r-- | test/files/jvm/varargs-separate-bytecode.check | 1 | ||||
-rw-r--r-- | test/files/jvm/varargs-separate-bytecode/AbstractProps_1.scala | 8 | ||||
-rw-r--r-- | test/files/jvm/varargs-separate-bytecode/Props_2.scala | 3 | ||||
-rw-r--r-- | test/files/jvm/varargs-separate-bytecode/Test.scala | 15 | ||||
-rw-r--r-- | test/files/jvm/varargs/JavaClass.java | 26 | ||||
-rw-r--r-- | test/files/jvm/varargs/VaClass.scala | 9 | ||||
-rw-r--r-- | test/files/jvm/varargs/varargs.scala | 16 | ||||
-rw-r--r-- | test/files/run/reflection-mem-typecheck.scala | 26 | ||||
-rw-r--r-- | test/files/run/t5125b.check | 3 | ||||
-rw-r--r-- | test/files/run/t5125b.scala | 12 |
14 files changed, 208 insertions, 65 deletions
diff --git a/test/files/jvm/t8786-sig.scala b/test/files/jvm/t8786-sig.scala new file mode 100644 index 0000000000..f22e400528 --- /dev/null +++ b/test/files/jvm/t8786-sig.scala @@ -0,0 +1,126 @@ +class A[U] { + @annotation.varargs def m1[T] (a: T*): T = a.head + @annotation.varargs def m2[T <: AnyRef](a: T*): T = a.head + @annotation.varargs def m3[T <: AnyVal](a: T*): T = a.head + @annotation.varargs def m4[T <: Int] (a: T*): T = a.head + @annotation.varargs def m5[T <: String](a: T*): T = a.head + @annotation.varargs def m6 (a: String*): String = a.head + @annotation.varargs def m7 (a: Int*): Int = a.head + @annotation.varargs def m8 (a: U*): U = a.head + + def n1[T] (a: Array[T]): T = a(0) + def n2[T <: AnyRef](a: Array[T]): T = a(0) + def n3[T <: AnyVal](a: Array[T]): T = a(0) + def n4[T <: Int] (a: Array[T]): T = a(0) + def n5[T <: String](a: Array[T]): T = a(0) + def n6 (a: Array[String]): String = a(0) + def n7 (a: Array[Int]): Int = a(0) + def n8 (a: Array[U]): U = a(0) +} + +object Test extends App { + val a = classOf[A[_]] + + def sig (method: String, tp: Class[_]) = a.getDeclaredMethod(method, tp).toString + def genSig(method: String, tp: Class[_]) = a.getDeclaredMethod(method, tp).toGenericString + def isVarArgs(method: String, tp: Class[_]) = a.getDeclaredMethod(method, tp).isVarArgs + def bound (method: String, tp: Class[_]) = { + val m = a.getDeclaredMethod(method, tp) + m.getGenericParameterTypes.apply(0) match { + case _: Class[_] => "" + case gat: java.lang.reflect.GenericArrayType => + val compTp = gat.getGenericComponentType.asInstanceOf[java.lang.reflect.TypeVariable[_]] + compTp.getBounds.apply(0).toString + } + } + + def check(found: String, expected: String): Unit = + assert(found == expected, s"found: $found\nexpected: $expected") + + def checkVarArgs(method: String, tp: Class[_])(expected: String): Unit = { + assert(isVarArgs(method, tp), s"expected varargs for $method") + val found = genSig(method, tp) + + def varArgsToBraces(sig: String) = sig.replaceAll("""\.\.\.""","[]") + // Normalize sigs so that the tests works on Java 6 (where varargs are printed as []) + // and above (where vargs are pretty printed using ...) + assert(varArgsToBraces(found) == varArgsToBraces(expected), s"found: $found\nexpected: $expected (modulo `...` or `[]` as varargs suffix)") + } + + val sq = classOf[Seq[_]] + val ob = classOf[Object] + val ao = classOf[Array[Object]] + val as = classOf[Array[String]] + val ai = classOf[Array[Int]] + + check(sig("m1", sq) , "public java.lang.Object A.m1(scala.collection.Seq)") + check(sig("m2", sq) , "public java.lang.Object A.m2(scala.collection.Seq)") + check(sig("m3", sq) , "public java.lang.Object A.m3(scala.collection.Seq)") + check(sig("m4", sq) , "public int A.m4(scala.collection.Seq)") + check(sig("m5", sq) , "public java.lang.String A.m5(scala.collection.Seq)") + check(sig("m6", sq) , "public java.lang.String A.m6(scala.collection.Seq)") + check(sig("m7", sq) , "public int A.m7(scala.collection.Seq)") + check(sig("m8", sq) , "public java.lang.Object A.m8(scala.collection.Seq)") + + check(genSig("m1", sq), "public <T> T A.m1(scala.collection.Seq<T>)") + check(genSig("m2", sq), "public <T> T A.m2(scala.collection.Seq<T>)") + check(genSig("m3", sq), "public <T> T A.m3(scala.collection.Seq<T>)") + // TODO: the signature for is wrong for T <: Int, SI-9846. The signature should be + // `public int A.m4(scala.collection.Seq<java.lang.Object>)`. This is testing the status quo. + check(genSig("m4", sq), "public <T> T A.m4(scala.collection.Seq<T>)") + check(genSig("m5", sq), "public <T> T A.m5(scala.collection.Seq<T>)") + check(genSig("m6", sq), "public java.lang.String A.m6(scala.collection.Seq<java.lang.String>)") + check(genSig("m7", sq), "public int A.m7(scala.collection.Seq<java.lang.Object>)") + check(genSig("m8", sq), "public U A.m8(scala.collection.Seq<U>)") + + + // varargs forwarder + + check(sig("m1", ao) , "public java.lang.Object A.m1(java.lang.Object[])") + check(sig("m2", ao) , "public java.lang.Object A.m2(java.lang.Object[])") + check(sig("m3", ao) , "public java.lang.Object A.m3(java.lang.Object[])") + check(sig("m4", ao) , "public int A.m4(java.lang.Object[])") + check(sig("m5", as) , "public java.lang.String A.m5(java.lang.String[])") + check(sig("m6", as) , "public java.lang.String A.m6(java.lang.String[])") + check(sig("m7", ai) , "public int A.m7(int[])") + check(sig("m8", ao) , "public java.lang.Object A.m8(java.lang.Object[])") + + checkVarArgs("m1", ao)("public <T> T A.m1(T...)") + checkVarArgs("m2", ao)("public <T> T A.m2(T...)") + checkVarArgs("m3", ao)("public <T> T A.m3(T...)") + // testing status quo: signature is wrong for T <: Int, SI-9846 + checkVarArgs("m4", ao)("public <T> T A.m4(T...)") + checkVarArgs("m5", as)("public <T> T A.m5(T...)") + checkVarArgs("m6", as)("public java.lang.String A.m6(java.lang.String...)") + checkVarArgs("m7", ai)("public int A.m7(int...)") + checkVarArgs("m8", ao)("public U A.m8(U...)") + + check(bound("m1", ao) , "class java.lang.Object") + check(bound("m2", ao) , "class java.lang.Object") + check(bound("m3", ao) , "class java.lang.Object") + check(bound("m4", ao) , "class java.lang.Object") + check(bound("m5", as) , "class java.lang.String") + check(bound("m6", as) , "") + check(bound("m7", ai) , "") + check(bound("m8", ao) , "class java.lang.Object") + + + check(sig("n1", ob) , "public java.lang.Object A.n1(java.lang.Object)") + check(sig("n2", ao) , "public java.lang.Object A.n2(java.lang.Object[])") + check(sig("n3", ob) , "public java.lang.Object A.n3(java.lang.Object)") + check(sig("n4", ob) , "public int A.n4(java.lang.Object)") + check(sig("n5", as) , "public java.lang.String A.n5(java.lang.String[])") + check(sig("n6", as) , "public java.lang.String A.n6(java.lang.String[])") + check(sig("n7", ai) , "public int A.n7(int[])") + check(sig("n8", ob) , "public java.lang.Object A.n8(java.lang.Object)") + + check(genSig("n1", ob), "public <T> T A.n1(java.lang.Object)") + check(genSig("n2", ao), "public <T> T A.n2(T[])") + check(genSig("n3", ob), "public <T> T A.n3(java.lang.Object)") + // testing status quo: signature is wrong for T <: Int, SI-9846 + check(genSig("n4", ob), "public <T> T A.n4(java.lang.Object)") + check(genSig("n5", as), "public <T> T A.n5(T[])") + check(genSig("n6", as), "public java.lang.String A.n6(java.lang.String[])") + check(genSig("n7", ai), "public int A.n7(int[])") + check(genSig("n8", ob), "public U A.n8(java.lang.Object)") +} diff --git a/test/files/jvm/t8786/A_1.scala b/test/files/jvm/t8786/A_1.scala new file mode 100644 index 0000000000..13c0ad191d --- /dev/null +++ b/test/files/jvm/t8786/A_1.scala @@ -0,0 +1,3 @@ +class A { + @annotation.varargs def foo[T](a: Int, b: T*): T = b.head +} diff --git a/test/files/jvm/t8786/B_2.java b/test/files/jvm/t8786/B_2.java new file mode 100644 index 0000000000..dc155a290f --- /dev/null +++ b/test/files/jvm/t8786/B_2.java @@ -0,0 +1,22 @@ +public class B_2 { + private static int res = 0; + + public static void m(char a[]) { res += 10; } + public static void m(String a) { res += 100; } + public static void m(Object a) { res += 1000; } + + public static <T> T foo(int a, T... b) { return b[0]; } + + public static <T> T bar(T b[]) { return b[0]; } + + public static void main(String[] args) { + m(foo(15, "a", "b", "c")); + if (res != 100) + throw new Error("bad: "+ res); + + A a = new A(); + m(a.foo(16, "a", "b", "c")); + if (res != 200) + throw new Error("bad: " + res); + } +} diff --git a/test/files/jvm/t8786/Test_2.scala b/test/files/jvm/t8786/Test_2.scala new file mode 100644 index 0000000000..76ccb4c3ed --- /dev/null +++ b/test/files/jvm/t8786/Test_2.scala @@ -0,0 +1,3 @@ +object Test extends App { + B_2.main(null) +} diff --git a/test/files/jvm/varargs-separate-bytecode.check b/test/files/jvm/varargs-separate-bytecode.check new file mode 100644 index 0000000000..1507cd48c5 --- /dev/null +++ b/test/files/jvm/varargs-separate-bytecode.check @@ -0,0 +1 @@ +Found vararg overload for method create
\ No newline at end of file diff --git a/test/files/jvm/varargs-separate-bytecode/AbstractProps_1.scala b/test/files/jvm/varargs-separate-bytecode/AbstractProps_1.scala new file mode 100644 index 0000000000..5dfb8d1a9e --- /dev/null +++ b/test/files/jvm/varargs-separate-bytecode/AbstractProps_1.scala @@ -0,0 +1,8 @@ +package foo + +import scala.annotation.varargs + +trait AbstractProps { + @varargs + def create(x: String, y: Int*): AbstractProps = null +} diff --git a/test/files/jvm/varargs-separate-bytecode/Props_2.scala b/test/files/jvm/varargs-separate-bytecode/Props_2.scala new file mode 100644 index 0000000000..3fc09586fc --- /dev/null +++ b/test/files/jvm/varargs-separate-bytecode/Props_2.scala @@ -0,0 +1,3 @@ +import foo.AbstractProps + +class Props extends AbstractProps
\ No newline at end of file diff --git a/test/files/jvm/varargs-separate-bytecode/Test.scala b/test/files/jvm/varargs-separate-bytecode/Test.scala new file mode 100644 index 0000000000..a666de7f39 --- /dev/null +++ b/test/files/jvm/varargs-separate-bytecode/Test.scala @@ -0,0 +1,15 @@ +import scala.collection.JavaConverters._ +import scala.tools.asm +import scala.tools.asm.Opcodes +import scala.tools.partest.BytecodeTest + +object Test extends BytecodeTest { + def show: Unit = { + val classNode = loadClassNode("Props") + val methods = classNode.methods.iterator().asScala.filter( m => m.name == "create") + + for (m <- methods if (m.access & Opcodes.ACC_VARARGS) > 0) { + println(s"Found vararg overload for method ${m.name}") + } + } +} diff --git a/test/files/jvm/varargs/JavaClass.java b/test/files/jvm/varargs/JavaClass.java index 6928ee5adc..0cc3587c5e 100644 --- a/test/files/jvm/varargs/JavaClass.java +++ b/test/files/jvm/varargs/JavaClass.java @@ -1,16 +1,12 @@ - - - public class JavaClass { - public static <T> void varargz(int i, T... v) { - } - - public static void callSomeAnnotations() { - VaClass va = new VaClass(); - va.vs(4, "", "", ""); - va.vi(1, 2, 3, 4); - varargz(5, 1.0, 2.0, 3.0); - va.vt(16, "", "", ""); - System.out.println(va.vt1(16, "a", "b", "c")); - } -}
\ No newline at end of file + public static <T> void varargz(int i, T... v) { } + + public static void callSomeAnnotations() { + VaClass va = new VaClass(); + va.vs(4, "", "", ""); + va.vi(1, 2, 3, 4); + varargz(5, 1.0, 2.0, 3.0); + va.vt(16, "", "", ""); + System.out.println(va.vt1(16, "a", "b", "c")); + } +} diff --git a/test/files/jvm/varargs/VaClass.scala b/test/files/jvm/varargs/VaClass.scala index d83e63ace1..ee8c288a16 100644 --- a/test/files/jvm/varargs/VaClass.scala +++ b/test/files/jvm/varargs/VaClass.scala @@ -1,15 +1,8 @@ - - import annotation.varargs - - class VaClass { - @varargs def vs(a: Int, b: String*) = println(a + b.length) @varargs def vi(a: Int, b: Int*) = println(a + b.sum) @varargs def vt[T](a: Int, b: T*) = println(a + b.length) - - // TODO remove type bound after fixing SI-8786, see also https://github.com/scala/scala/pull/3961 - @varargs def vt1[T <: String](a: Int, b: T*): T = b.head + @varargs def vt1[T](a: Int, b: T*): T = b.head } diff --git a/test/files/jvm/varargs/varargs.scala b/test/files/jvm/varargs/varargs.scala index 6d2e707bdf..b09818f46f 100644 --- a/test/files/jvm/varargs/varargs.scala +++ b/test/files/jvm/varargs/varargs.scala @@ -1,21 +1,5 @@ - - - - - - object Test { def main(args: Array[String]) { JavaClass.callSomeAnnotations } } - - - - - - - - - - diff --git a/test/files/run/reflection-mem-typecheck.scala b/test/files/run/reflection-mem-typecheck.scala deleted file mode 100644 index f1fe983ede..0000000000 --- a/test/files/run/reflection-mem-typecheck.scala +++ /dev/null @@ -1,26 +0,0 @@ -import scala.tools.partest.MemoryTest - -trait A { type T <: A } -trait B { type T <: B } - -object Test extends MemoryTest { - lazy val tb = { - import scala.reflect.runtime.universe._ - import scala.reflect.runtime.{currentMirror => cm} - import scala.tools.reflect.ToolBox - cm.mkToolBox() - } - - override def maxDelta = 12 - override def calcsPerIter = 8 - override def calc() { - var snippet = """ - trait A { type T <: A } - trait B { type T <: B } - def foo[T](x: List[T]) = x - foo(List(new A {}, new B {})) - """.trim - snippet = snippet + "\n" + (List.fill(50)(snippet.split("\n").last) mkString "\n") - tb.typecheck(tb.parse(snippet)) - } -}
\ No newline at end of file diff --git a/test/files/run/t5125b.check b/test/files/run/t5125b.check index ddbf908f04..29b438a2d6 100644 --- a/test/files/run/t5125b.check +++ b/test/files/run/t5125b.check @@ -5,3 +5,6 @@ public void C2.f(scala.collection.Seq) public void C2$C3.f(java.lang.String[]) public void C2$C3.f(scala.collection.Seq) public void C4.f(scala.collection.Seq) +private void C5.f(int,int[]) +private void C5.f(int,scala.collection.Seq) +public void C5.f(scala.collection.Seq) diff --git a/test/files/run/t5125b.scala b/test/files/run/t5125b.scala index 149c49e213..60ab1d9792 100644 --- a/test/files/run/t5125b.scala +++ b/test/files/run/t5125b.scala @@ -23,6 +23,17 @@ class C4 { } } +class C5 { + def f(values: String*) = println("Calling C5.f(): " + values) + @scala.annotation.varargs + private def f(v: Int, values: Int*) = println("Calling C5.f(): " + values) + + def method(): Unit = { + @scala.annotation.varargs + def f(values: String*) = println("Calling C5.<locally>.f(): " + values) + } +} + object Test extends App { def check(c: Class[_]) { val methodName = "f" @@ -34,4 +45,5 @@ object Test extends App { check(classOf[C2]) check(classOf[C2#C3]) check(classOf[C4]) + check(classOf[C5]) } |