Bug 317586 - [1.5][compiler] Compilation error with eclipse while standard javac succeeds
Summary: [1.5][compiler] Compilation error with eclipse while standard javac succeeds
Status: VERIFIED INVALID
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.7 M1   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-06-22 10:36 EDT by Maarten Coene CLA
Modified: 2010-08-03 07:08 EDT (History)
3 users (show)

See Also:


Attachments
Example java file (371 bytes, application/octet-stream)
2010-06-22 10:37 EDT, Maarten Coene CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Maarten Coene CLA 2010-06-22 10:36:17 EDT
Build Identifier: 20091217-0918

Hi,

we have a class that doesn't compile with the eclipse compiler. However, when using the standard Java compiler, it works without a problem.

I'll attach an example of such a class that Eclipse cannot compile.

Reproducible: Always
Comment 1 Maarten Coene CLA 2010-06-22 10:37:54 EDT
Created attachment 172418 [details]
Example java file
Comment 2 Maarten Coene CLA 2010-06-22 10:39:39 EDT
Forgot to mention, the compilation error is:
"The method min(Integer, Integer[]) is ambiguous for the type Tools"

We also have this problem with Eclipse 3.5.2 and 3.6RC4
Comment 3 Srikanth Sankaran CLA 2010-06-23 02:12:52 EDT
Will follow up, but it is worth noting that JDK7 (b91) refuses
to compile this code with a complaint about reference to min
being ambigious.
Comment 4 Srikanth Sankaran CLA 2010-06-30 01:24:02 EDT
See that this also refuses to compile with javac 5.
See bug 303814 comment 3 which applies to this case
as well, but for wording specific to the test case
there.

*** This bug has been marked as a duplicate of bug 303814 ***
Comment 5 Maarten Coene CLA 2010-06-30 02:18:30 EDT
Please note there is a difference with bug 303814.
The attached example to this bug does compile with a SUN javac 6, while the example with bug 303814 doesn't.
Comment 6 Srikanth Sankaran CLA 2010-06-30 02:49:39 EDT
(In reply to comment #5)
> Please note there is a difference with bug 303814.
> The attached example to this bug does compile with a SUN javac 6, while the
> example with bug 303814 doesn't.

I believe that is due to a bug in javac 6 which has since been fixed in
JDK7. We have seen many instances where javac fixes the defect only in
JDK7 stream and not back port it to JDK6.

Per earlier comment, this code also does not compile with javac 5.

Our goal is not to be bug compatible with javac and so there is not
much anything we can do here.
Comment 7 Srikanth Sankaran CLA 2010-07-01 04:49:05 EDT
(In reply to comment #5)
> Please note there is a difference with bug 303814.
> The attached example to this bug does compile with a SUN javac 6, while the
> example with bug 303814 doesn't.

Hello Maarten,

See that the slightly modified program below fails to compile
on all flavors: javac 5,6,7 with the same error message as
eclipse produces. The current test case hard codes the Integer
type which in your case was inferred. Other than that there are
no differences. 

public class Tools {    
    public static void main(String[] args) {
    	min(1, new Integer(5), new Integer(8));
    }

    public static Integer min(Integer o1, Integer... o2) {
        return null;
    }

    public static Integer min(int extremum, Integer o1, Integer... o2) {
        return null;
    }
}

On your original test case, the javac7 vintage compiler has been
reporting errors since build b25 dated: 04/10/08.

So I propose to close the current bug as INVALID.
Comment 8 Maarten Coene CLA 2010-07-01 17:22:21 EDT
I've read your comment in the other bug report and read the JSL 3.0 trying to understand why it should throw this ambiguous error.

If I understand correctly, this error is thrown because the first parameter of type 'int' is not a subtype of the first parameter of the other method, which is 'Integer' (cfr 15.12.2.5).

So the following compiles because all parameters of the first method (String) are subtypes of the parameters of the second method (Object):

public class Tools {
    public static void main(String[] args) {
    	min("a", "b", "c");
    }
    public static void min(String a, String b, String... c) {}
    public static void min(Object a, Object... b) {}
}

However, there must be something wrong with this reasoning because the following doesn't compile (with eclipse or javac), even though String is a subtype of Comparable:

public class Tools {
    public static void main(String[] args) {
    	min("a", "b", "c");
    }
    public static void min(Comparable a, Comparable b, Comparable... c) {}
    public static void min(Object a, Object... b) {}
}

In addition, if both methods have the same type of arguments, it compiles again:

public class Tools {
    public static void main(String[] args) {
    	min("a", "b", "c");
    }
    public static void min(Comparable a, Comparable... b) {}
    public static void min(Object a, Object... b) {}
}

This makes me suspect there is something wrong with my reasoning that it should compile if all parameters of the first method are subtypes of the parameters of the second method.

So could you please explain why this shouldn't compile according to the JSL?

thanks,
Maarten
Comment 9 Srikanth Sankaran CLA 2010-07-02 01:21:19 EDT
(In reply to comment #8)
> I've read your comment in the other bug report and read the JSL 3.0 trying to
> understand why it should throw this ambiguous error.

> If I understand correctly, this error is thrown because the first parameter of
> type 'int' is not a subtype of the first parameter of the other method, which
> is 'Integer' (cfr 15.12.2.5).

As I noted in comment#4, there is some wording in the other bug
that is specific to the code fragment there. 

This argument of subtype or not was used to show why neither method
is "more specific" than the other. Please see below:

> So the following compiles because all parameters of the first method (String)
> are subtypes of the parameters of the second method (Object):
> 
> public class Tools {
>     public static void main(String[] args) {
>         min("a", "b", "c");
>     }
>     public static void min(String a, String b, String... c) {}
>     public static void min(Object a, Object... b) {}
> }

By 15.12.2.5 (... The informal intuition is that one method is more
specific than another if any invocation handled by the first method
could be passed on to the other one without a compile-time type error...)

min(String a, String b, String... c) is more specific than
min(Object a, Object... b) since any invocation handled by the
former can be passed onto the latter.

The reverse is not true since some invocations handled by
min(Object a, Object... b)  cannot be handled by min(String a, String b, String... c). For example, the call 

    min (new Object(), new Object());

cannot be handled by the String version.

So, min(String, String, String ...) is "strictly more specific"
and also "maximally" specific for the invocation. Since there is
only one method that is maximally specific, that method is also
the "most specific method" and so the call is not ambiguous and
to binds to the most specific method (min(String, String, String ...)

This explains why the case above compiles alright.

> However, there must be something wrong with this reasoning because the
> following doesn't compile (with eclipse or javac), even though String is a
> subtype of Comparable:
> 
> public class Tools {
>     public static void main(String[] args) {
>         min("a", "b", "c");
>     }
>     public static void min(Comparable a, Comparable b, Comparable... c) {}
>     public static void min(Object a, Object... b) {}
> }

The above is a perfectly valid program that compiles fine with eclipse
as well as javac5,6,7. You can follow the same reasoning as above
to show that min(Comparable a, Comparable b, Comparable... c) is
maximally specific and so is the most specific method for the call
you have.

> In addition, if both methods have the same type of arguments, it compiles
> again:

No surprise here.
Comment 10 Srikanth Sankaran CLA 2010-07-02 02:13:49 EDT
Here is categorical proof that this is a javac bug and the call is
indeed ambiguous:

Returning to your original test case:
public class Tools {    
    public static void main(String[] args) {
    	min(1, new Integer(5), new Integer(8));
    }

    public static <C extends Comparable<? super C>> C min(C o1, C... o2) {
        return null;
    }

    public static <C extends Comparable<? super C>> C min(int extremum, C o1, C... o2) {
        return null;
    }
}

The call min(1, new Integer(5), new Integer(8)) is ambiguous because
both of the methods could satisfy the invocation and neither is more
specific than the other and they are not override equivalent.

Proof that neither is more specific than the other:

(1) the call to min(new Integer(5)); if inserted in main() above
could be bound to C min(C o1, C... o2) and cannot be bound to
min(int extremum, C o1, C... o2); so C min(C o1, C... o2) is
NOT more specific than min(int extremum, C o1, C... o2);


(2) The call to min(10, 10, new Integer [] { 10 }); if inserted
in main above, can only be serviced by min(int extremum, C o1, C... o2);
and never by C min(C o1, C... o2). So min(int extremum, C o1, C... o2)
is NOT more specific than C min(C o1, C... o2)

(3) Since neither method is more specific, neither is strictly more
specific and BOTH ARE maximally specific.

(4) Since the method involved are not override equivalent, the method
call is ambiguous.

I could have perhaps helped your case by establishing this case earlier
rather than pointing to duplicate which is very very similar, but not
identical.

So rather than close this as duplicate, I'll close this as INVALID
this time.
Comment 11 Srikanth Sankaran CLA 2010-07-02 02:15:35 EDT
Set wrong resolution by mistake, resetting to INVALID.
Comment 12 Ayushman Jain CLA 2010-08-03 07:08:20 EDT
Verified for 3.7M1.