On 06/09/2011 04:46 PM, Kirk wrote:
+1 Charlie, it's edgy-casey

At this point, I'd ask the question, do you change the behavior or change the spec.

If you change the spec Attila will kill you :)
His MOP implements the spec not the javac behavior.

Changing the spec means changing all implementations based on the spec,
the Java method resolution algorithm is not used only in Java compilers.


Regards,
Kirk

cheers,
Rémi


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 <mailto: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>
    <mailto:head...@headius.com>
    Reply-To:   jvm-languages@googlegroups.com
    <mailto:jvm-languages@googlegroups.com>
    To:         JVM Languages <jvm-languages@googlegroups.com>
    <mailto:jvm-languages@googlegroups.com>
    CC:         Mark Reinhold <mark.reinh...@oracle.com>
    <mailto: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 tojvm-langua...@googlegroups.com  
<mailto:jvm-languages@googlegroups.com>.
    To unsubscribe from this group, send email 
tojvm-languages+unsubscr...@googlegroups.com  
<mailto:jvm-languages+unsubscr...@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@googlegroups.com <mailto:jvm-languages@googlegroups.com>. To unsubscribe from this group, send email to jvm-languages+unsubscr...@googlegroups.com <mailto: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.

Reply via email to