+1 Charlie, it's edgy-casey At this point, I'd ask the question, do you change the behavior or change the spec.
Regards, Kirk On Jun 9, 2011, at 4:36 PM, Charles Oliver Nutter wrote: > I accept this analysis as written. I do however have a few questions/comments. > > * This seems like it only affects cases where you have primitives butting up > against a varargs Object..., correct? Only in those cases do you have a > method invocation conversion from a type that does not subclass Object. > Edge-casey. > > * It is unexpected, albeit correct according to specification. A few reasons: > > ** The int => Object conversion is via Integer, which *is* a subtype > relationship. I know the spec does not provide for reevaluating specificity > after a method invocation conversion...but perhaps it should. > > ** int *is* more specific than Object from a programmer/development > perspective. Another way of looking at specificity would be "fewer > combinations of argument types apply". That's clearly the case here. > > I suspect I won't be the only one to run into this new behavior. As it > stands, the methods in question in JRuby no longer need the varargs forms, so > I'm removing them. > > - Charlie > > On Thu, Jun 9, 2011 at 9:24 AM, Maurizio Cimadamore > <maurizio.cimadam...@oracle.com> wrote: > Remi, your analysis is correct. > > Consider the method call: > > method("str", 1); > > Now, you have two potentially applicable methods, namely > > - method(String str, int num, Object... data) > - method(String str, Object... data) > > Since both are varargs method, both methods can only be applicable by > variable arity method conversion (see JLS 15.12.2.4). Both methods are > applicable (note that the second method is applicable since there exist a > method invocation conversion to go from int to Object). > > Since both are applicable we have now to choose the most specific (see > 15.12.2.5) - the rules says that: > > "In addition, one variable arity member method named m is more specific than > another variable arity member method of the same name if either: > > *) One member method has n parameters and the other has k parameters, where n > >= k. The types of the parameters of the first member method are T1, . . . , > Tn-1 , Tn[], the types of the parameters of the other method are U1, . . . , > Uk-1, Uk[]. [...] otherwise let Si = Ui, 1 < i <=k. Then: > > - for all j from 1 to k-1, Tj <: Sj, and, > - for all j from k to n, Tj <: Sk, and, > > *) One member method has k parameters and the other has n parameters, where > n>=k. The types of the parameters of the first method are U1, . . . , Uk-1, > Uk[], the types of the parameters of the other method are T1, . . ., Tn-1, > Tn[]. [...] otherwise let Si = Ti, 1 <i <= n. Then: > > - for all j from 1 to k-1 , Uj <: Sj, and, > - for all j from k to n , Uk <: Sj, and," > > *** Part 1 > > So, is M1 = method(String str, int num, Object... data) more specific than M2 > = method(String str, Object... data) ? Since arity of M1 is bigger than arity > of M2, the first bullet apply. More specifically, n is 3, k is 2, T = { > String, int, Object }, while S = U = { String, Object }. We have to prove > that: > > - for all j from 1 to 1 (as k is 2), Tj <: Sj, and, > - for all j from 2 to 3, Tj <: S2, and, > > Which means: > > j = 1 --> T1 <: S1 ? Yes, because String <: String > j = 1 --> T2 <: S2 ? No, because int is not a subtype of Object > > Which means method(String str, int num, Object... data) is not more specific > than method(String str, Object... data). Let's try the other way around. > > *** Part 2 > > So, is M1 = method(String str, Object... data) more specific than M2 = > method(String str, int i, Object... data) ? Since arity of M1 is smaller than > arity of M2, the second bullet apply. More specifically, n is 2, k is 3, U = > { String, Object }, S = T = { String, int, Object }. We have to prove that: > > - for all j from 1 to 2 (as k is 3), Uj <: Sj, and, > - for all j from 3 to 3, Uj <: S3, and, > > Which means: > > j = 1 --> U1 <: S1 ? Yes, because String <: String > j = 1 --> U2 <: S2 ? No, because int is not a subtype of Object > > Which means method(String str, Object... data) is not more specific than > method(String str, int i, Object... data). The conclusion is that neither > method is more specific than the other, so the compile-time error is > legitimate. > > Maurizio > > > > > On 09/06/11 14:51, Rémi Forax wrote: >> >> add compiler dev-list to the loop. >> >> My analysis is that this is a fix for a previously existing bug, >> so the behavior of javac is now correct. >> >> With method("str", 1), no method are applicable without considering boxing >> and varargs, >> so we ends up with phase 3. Here, both boxing and varargs are enabled so >> the two method are applicable and not one is most specific. >> So the call is ambiguous. >> >> Rémi >> >> -------- Original Message -------- >> Subject: [jvm-l] Newly introduced OpenJDK javac bug? >> Date: Thu, 9 Jun 2011 08:26:04 -0500 >> From: Charles Oliver Nutter <head...@headius.com> >> Reply-To: jvm-languages@googlegroups.com >> To: JVM Languages <jvm-languages@googlegroups.com> >> CC: Mark Reinhold <mark.reinh...@oracle.com> >> >> Recent OpenJDK 7 builds seem to have introduced a bug into javac. >> Correct me if I'm wrong. >> >> https://gist.github.com/1016436 >> >> public class Foo { >> public static void main(String[] args) { >> method("str"); >> method("str", 1); >> method("str", 1, "data"); >> } >> >> public static void method(String str, int num, Object... data) { >> // do nothing >> } >> >> public static void method(String str, Object... data) { >> // do nothing >> } >> } >> >> It seems that the order in which it attempts to apply varargs and >> boxing has changed. On OpenJDK/Hotspot 1.6.x and OpenJDK 7 builds >> prior to 143, this compiles fine and calls the first signature for all >> calls. My interpretation of the Java specification is that this is >> correct behavior; the more exact signature that requires no boxing is >> chosen rather than the second signature which does require boxing. >> >> However on later builds, we get the following errors for this case: >> >> Foo.java:4: error: reference to method is ambiguous, both method >> method(String,int,Object...) in Foo and method >> method(String,Object...) in Foo match >> method("str", 1); >> ^ >> Foo.java:5: error: reference to method is ambiguous, both method >> method(String,int,Object...) in Foo and method >> method(String,Object...) in Foo match >> method("str", 1, "data"); >> >> Both invocations fall through to phase 3 of method selection, variable >> arity. But in this case, I believe the first signature (with int) >> should resolve as "more specific" than the second, and should be >> chosen for both invocations. I admit it's a grey area, however, and I >> can't find a specific clause in the Java spec to back me up. >> >> I'm not sure who to talk to about this, or whether I'm right in >> thinking this is a new bug in javac. Thoughts? >> >> - Charlie >> >> -- >> You received this message because you are subscribed to the Google Groups >> "JVM Languages" group. >> To post to this group, send email to jvm-languages@googlegroups.com. >> To unsubscribe from this group, send email to >> jvm-languages+unsubscr...@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/jvm-languages?hl=en. >> > > > > -- > You received this message because you are subscribed to the Google Groups > "JVM Languages" group. > To post to this group, send email to jvm-languages@googlegroups.com. > To unsubscribe from this group, send email to > jvm-languages+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/jvm-languages?hl=en. -- You received this message because you are subscribed to the Google Groups "JVM Languages" group. To post to this group, send email to jvm-languages@googlegroups.com. To unsubscribe from this group, send email to jvm-languages+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/jvm-languages?hl=en.