This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 200024 - Incorrectly-applied error hint "reference to ... is ambiguous, both method ... in ... and method ... in ... match"
Summary: Incorrectly-applied error hint "reference to ... is ambiguous, both method .....
Status: RESOLVED WONTFIX
Alias: None
Product: java
Classification: Unclassified
Component: Hints (show other bugs)
Version: 7.0.1
Hardware: PC Windows 7 x64
: P3 normal (vote)
Assignee: Jan Lahoda
URL:
Keywords:
Depends on: 198366
Blocks:
  Show dependency tree
 
Reported: 2011-07-10 22:59 UTC by dtrebbien
Modified: 2012-01-23 08:59 UTC (History)
1 user (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Screenshot (31.07 KB, image/png)
2011-07-10 22:59 UTC, dtrebbien
Details

Note You need to log in before you can comment on or make changes to this bug.
Description dtrebbien 2011-07-10 22:59:08 UTC
Created attachment 109353 [details]
Screenshot

The error hint for ambiguous method call is sometimes incorrect;  sometimes the error hint appears when the target method of the call is not ambiguous.

This is a problem with 7.0.1 RC1, but not 7.0 Patch 1.

Steps to reproduce:
1.  Add the following source file to a Java project (1.6 sources):

    package test;

    public class Test {
        public static void column(int i, int j, Object... args) {
            System.out.println("column(int, int, Object...)");
        }

        public static void column(Object... args) {
            System.out.println("column(Object...)");
        }

        public static void main(String[] args) {
            column(0, 1, new Object());
            column(Integer.valueOf(0), Integer.valueOf(1), new Object());
        }
    }

2.  Momentarily, NetBeans will squiggly-underline both calls to column(int, int, Object...) in main(String[]).  The error message for each is "reference to column is ambiguous, both column(int, int, java.lang.Object...) in test.Test and method column(java.lang.Object...) in test.Test match".  See the attached screenshot.
3.  Right click on the newly-added file in the Projects window and select "Run File".  Compilation succeeds and the output is:

    column(int, int, Object...)
    column(int, int, Object...)
Comment 1 Jan Lahoda 2011-07-26 14:26:03 UTC
I am sorry, but this error adheres to the Java language specification and is therefore considered to be correct. This is the answer I got about it:

Long answer: the problem is that the JLS use subtyping (not assignability) in order to select most specific method - which means that, after you logically expanded the two signatures to fit their respective arity, you have a straight most specific test between:

test(int, Object)

test(Object, Object)

The problem is that the first argument is unrelated (by subtyping) w.r.t. the second argument, which means neither method is more specific than the other.

Note that, w/o varargs it is not possible to come up with the above most specific test because, if the above method where fixed arity, the compiler will either choose the first signature or the second depending on whether the first argument is primitive or not. But once you go through variable arity method checking, both methods become applicable, which means the most specific algorithm has to pick the 'best' one, and, since it only uses subtyping, it cannot decide between the two.
Comment 2 MarkFlacy 2012-01-22 00:37:41 UTC
That's all very nice, except that javac itself (version 1.6 at least) has absolutely no problem compiling and running the code that Netbeans flags as in error.  Javac does not even emit a warning!

As for your example, the JLS states that the second phase (§15.12.2.3) allows boxing and unboxing which would expand the method signatures to...

test(Integer, Object)
test(Object, Object)

...and the first signature is more specific than the second since you can convert an Integer to an Object but not vice versa.

At the very least, since this can and does produce false positives, allow the user to configure this to be a warning.
Comment 3 Jan Lahoda 2012-01-23 08:59:30 UTC
(I assume that we are still talking about the original test case with vararg methods.)

(In reply to comment #2)
> That's all very nice, except that javac itself (version 1.6 at least) has
> absolutely no problem compiling and running the code that Netbeans flags as in
> error.  Javac does not even emit a warning!

Javac from JDK7 reports the exact same error as you can see in NetBeans. To the best of my knowledge, it is a bug that this code is compilable with JDK6 javac (the answer above is for a javac developer).
Sorry, but it is not in our power to provide bug-to-bug compatibility with all compilers.

> 
> As for your example, the JLS states that the second phase (§15.12.2.3) allows

I am afraid that the second phase is not (that much) important. Both column methods are becoming applicable in the third phase, due to the varargs (try to wrap the "vararg" part of the invocation with an explicit new Object [] {...}, to eliminate phase 3 of application method evaluation - there is no compile-time error in such a case).

> boxing and unboxing which would expand the method signatures to...
> 
> test(Integer, Object)
> test(Object, Object)

Sorry, but this is not correct (to my understanding). The actual argument's type is subject to conversion by the method invocation conversion while the compiler is trying to find applicable methods - the method signature is not altered). Once applicable methods are found, §15.12.2.5 is used to find the most specific one (using the original method signatures), but that algorithm cannot decide between the methods. The reason is that int is not a subtype of Object, and vice versa.

> 
> ...and the first signature is more specific than the second since you can
> convert an Integer to an Object but not vice versa.
> 
> At the very least, since this can and does produce false positives, allow the
> user to configure this to be a warning.

Sorry, but no. Doing that for all ambiguous errors would be too dangerous (there are many more (simpler) cases where a method invocation may be ambiguous). Messing with method invocation algorithm to allow this specific case (e.g. for source level==1.6) is way too dangerous. And I don't think it is a good idea anyway: the code is not valid as per spec, newer javac won't compile it, and I believe that it is better to know this rather sooner than later.