From d7b99c3c33de8d759353c7ffd1d89e2cb38d793b Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 10 Mar 2015 23:54:39 -0700 Subject: SI-9102: Reflect method invoke with mixed args A missing default branch when a method had value class or by-name params caused other args to present as null under reflective invocation. --- test/files/run/t9102.scala | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 test/files/run/t9102.scala (limited to 'test') diff --git a/test/files/run/t9102.scala b/test/files/run/t9102.scala new file mode 100644 index 0000000000..37ae53b2ab --- /dev/null +++ b/test/files/run/t9102.scala @@ -0,0 +1,73 @@ + +object Test extends App { + import reflect.runtime._, universe._ + + class C { def f(i: Int, j: => Int) = i + j } + + class V(val v: Int) extends AnyVal { def doubled = 2 * v } + class D { def f(i: Int, j: V) = i + j.doubled } + + locally { + val ms = typeOf[C].member(TermName("f")).asMethod + val im = currentMirror reflect (new C) + val mm = im reflectMethod ms + assert(mm(2,3) == 5) + } + locally { + val ms = typeOf[D].member(TermName("f")).asMethod + val im = currentMirror reflect (new D) + val mm = im reflectMethod ms + assert(mm(2, new V(3)) == 8) + } +} + +/* Session tests without special init code should reside in simple script files. + * Also, provide filters such as for `(bound to C@74f7d1d2)`. + +import scala.tools.partest.SessionTest + +object Test extends SessionTest { +//Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40). + def session = + s"""|Type in expressions to have them evaluated. + |Type :help for more information. + | + |scala> import reflect.runtime._, universe._ + |import reflect.runtime._ + |import universe._ + | + |scala> class C { def f(i: Int, j: => Int) = i + j } + |defined class C + | + |scala> typeOf[C].member(TermName("f")) + |res0: reflect.runtime.universe.Symbol = method f + | + |scala> .asMethod + |res1: reflect.runtime.universe.MethodSymbol = method f + | + |scala> currentMirror reflect (new C) + |res2: reflect.runtime.universe.InstanceMirror = instance mirror for C@74f7d1d2 + | + |scala> res2 reflectMethod res1 + |res3: reflect.runtime.universe.MethodMirror = method mirror for def f(i: scala.Int,j: => scala.Int): scala.Int (bound to C@74f7d1d2) + | + |scala> res3(2,3) + |res4: Any = 5 + | + |scala> :quit""" +} +*/ + +/* was: +scala> res3(2,3) +java.lang.IllegalArgumentException + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:497) + at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaMethodMirror.jinvokeraw(JavaMirrors.scala:335) + at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaMethodMirror.jinvoke(JavaMirrors.scala:339) + at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaTransformingMethodMirror.apply(JavaMirrors.scala:436) + ... 33 elided +*/ + -- cgit v1.2.3 From 0a8dfd927e6362656b541360cf6920c2c7c69b08 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 11 Mar 2015 10:04:27 -0700 Subject: SI-9102: Improve test Cover the second use case reported on the ML (ctors). Improve formatting per the review. And it really does look a lot better. --- src/reflect/scala/reflect/runtime/JavaMirrors.scala | 8 ++++---- test/files/run/t9102.scala | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 7d72833d64..3b497227e7 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -429,10 +429,10 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive while (i < args1.length) { val arg = args(i) args1(i) = ( - if (i >= paramCount) arg // don't transform varargs - else if (isByName(i)) () => arg // don't transform by-name value class params - else if (isDerivedValueClass(i)) paramUnboxers(i).invoke(arg) - else arg + if (i >= paramCount) arg // don't transform varargs + else if (isByName(i)) () => arg // don't transform by-name value class params + else if (isDerivedValueClass(i)) paramUnboxers(i).invoke(arg) // do get the underlying value + else arg // don't molest anything else ) i += 1 } diff --git a/test/files/run/t9102.scala b/test/files/run/t9102.scala index 37ae53b2ab..c46cf0e4b4 100644 --- a/test/files/run/t9102.scala +++ b/test/files/run/t9102.scala @@ -7,6 +7,8 @@ object Test extends App { class V(val v: Int) extends AnyVal { def doubled = 2 * v } class D { def f(i: Int, j: V) = i + j.doubled } + class E(i: Int, j: V) + locally { val ms = typeOf[C].member(TermName("f")).asMethod val im = currentMirror reflect (new C) @@ -19,6 +21,12 @@ object Test extends App { val mm = im reflectMethod ms assert(mm(2, new V(3)) == 8) } + locally { + val ms = typeOf[E].typeSymbol.asClass.primaryConstructor + val cm = currentMirror reflectClass typeOf[E].typeSymbol.asClass + val mm = cm reflectConstructor ms.asMethod + assert(mm(42, new V(7)).isInstanceOf[E]) + } } /* Session tests without special init code should reside in simple script files. -- cgit v1.2.3