Fwd: [jvm-l] Newly introduced OpenJDK javac bug?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Jun 9 08:30:28 PDT 2011
On 09/06/11 15:52, Robert Fischer wrote:
> I've been using precisely the pattern that Charlie lays out in some of
> my code, as well, so I'm going to have to code around it now. I didn't
> realize that it was technically ambiguous — it's really surprising to
> my intuition, which (I'm now realizing as I think about it) tries to
> match arguments left to right, and only drops to varargs if it can't
> find a match. That intuition is obviously wrong compared to the spec,
> but does that mean we have a bug in the spec? What's the justification
> for this behavior?
This seems to be an area where things can be improved. Note that the JDK
7 algorithm has been brought in sync with the spec because we had other
bugs in which the compiler was issuing bad error messages (esp. with
varargs with primitive types, see [1] and related issues).
[1] - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6199075
Maurizio
>
> For the record, both Scala and Groovy resolve methods more in line
> with intuition:
> Groovy > https://gist.github.com/1016878
> Scala > https://gist.github.com/1016880
>
> ~~ Robert.
>
> On Thu, Jun 9, 2011 at 10:36 AM, Charles Oliver Nutter
> <headius at headius.com <mailto:headius at headius.com>> 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.cimadamore at oracle.com
> <mailto: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>
>> <mailto:headius at headius.com>
>> Reply-To: jvm-languages at googlegroups.com
>> <mailto:jvm-languages at googlegroups.com>
>> To: JVM Languages <jvm-languages at googlegroups.com>
>> <mailto:jvm-languages at googlegroups.com>
>> CC: Mark Reinhold <mark.reinhold at oracle.com>
>> <mailto: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 tojvm-languages at googlegroups.com <mailto:jvm-languages at googlegroups.com>.
>> To unsubscribe from this group, send email tojvm-languages+unsubscribe at googlegroups.com <mailto:jvm-languages+unsubscribe at googlegroups.com>.
>> For more options, visit this group athttp://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 at googlegroups.com
> <mailto:jvm-languages at googlegroups.com>.
> To unsubscribe from this group, send email to
> jvm-languages+unsubscribe at googlegroups.com
> <mailto:jvm-languages%2Bunsubscribe 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/82caf335/attachment.html
More information about the compiler-dev
mailing list