Fwd: [jvm-l] Newly introduced OpenJDK javac bug?
Charles Oliver Nutter
headius at headius.com
Thu Jun 9 07:36:14 PDT 2011
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.cimadamore at 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 <headius at headius.com> <headius at headius.com> Reply-To:
> jvm-languages at googlegroups.com To: JVM Languages
> <jvm-languages at googlegroups.com> <jvm-languages at googlegroups.com> CC: Mark
> Reinhold <mark.reinhold at oracle.com> <mark.reinhold at 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 at googlegroups.com.
> To unsubscribe from this group, send email to jvm-languages+unsubscribe at googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/jvm-languages?hl=en.
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20110609/923ffa2c/attachment.html
More information about the compiler-dev
mailing list