JDK-6356673 : javac incorrectly generates "reference to is ambiguous"
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0,6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-11-29
  • Updated: 2017-05-16
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 Other
6u10Fixed 7 b05Fixed OpenJDK6Resolved
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
The overload resolution mechansm for javac 1.5 seems not to cope with the pattern used in the attached code

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile the test application

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
should compile and resolve the overload
ACTUAL -
javac failed, with error deatiled below

ERROR MESSAGES/STACK TRACES THAT OCCUR :
reference to addAll is ambiguous, both method addAll(java.util.Collection<? extends E>) in java.util.Collection<? super A> and method addAll(java.util.Collection<? extends E>) in java.util.List<? super A> match
        l.addAll(getRelated(b));

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.Collections;
import java.util.List;


public class Test<A,B> {

    private List<A> getRelated(B b) {
        return Collections.emptyList();
    }
    
    public <L extends List<? super A>> L addOrCreate(B b,L l) {
        l.addAll(getRelated(b));
        return l;
    }
    
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
dont use this pattern, chnage to interfaces, and developed code.
Simplified testcase submitted by another customer:

import java.util.Set;

public class GenericCaptureAddingTest {

    public void test(Set<? super Number> numbers, Set<Number> someNumbers) {
        numbers.addAll(someNumbers);
    }

}

Comments
SUGGESTED FIX Webrev of changes: http://sa.sfbay/projects/langtools/bugid_summary.pl?bugid=6356673 See also attachment 6356673.tar.gz.
27-11-2006

SUGGESTED FIX Index: j2se/src/share/classes/com/sun/tools/javac/code/Types.java --- /tmp/geta9696 2006-11-26 22:28:10.000000000 -0800 +++ /tmp/getb9696 2006-11-26 22:28:10.000000000 -0800 @@ -776,14 +776,16 @@ } void debugContainsType(WildcardType t, Type s) { + System.err.println(); + System.err.format(" does %s contain %s?%n", t, s); System.err.format(" %s U(%s) <: U(%s) %s = %s%n", - upperBound(s), s, t, upperBound(t), + upperBound(s), s, t, U(t), t.isSuperBound() - || isSubtypeNoCapture(upperBound(s), upperBound(t))); + || isSubtypeNoCapture(upperBound(s), U(t))); System.err.format(" %s L(%s) <: L(%s) %s = %s%n", - lowerBound(t), t, s, lowerBound(s), + L(t), t, s, lowerBound(s), t.isExtendsBound() - || isSubtypeNoCapture(lowerBound(t), lowerBound(s))); + || isSubtypeNoCapture(L(t), lowerBound(s))); System.err.println(); } @@ -793,8 +795,10 @@ return containedBy(s, t); else { // debugContainsType(t, s); - return (t.isExtendsBound() || isSubtypeNoCapture(L(t), lowerBound(s))) - && (t.isSuperBound() || isSubtypeNoCapture(upperBound(s), U(t))); + return isSameWildcard(t, s) + || isCaptureOf(s, t) + || ((t.isExtendsBound() || isSubtypeNoCapture(L(t), lowerBound(s))) && + (t.isSuperBound() || isSubtypeNoCapture(upperBound(s), U(t)))); } } @@ -812,6 +816,19 @@ } }; + public boolean isCaptureOf(Type s, WildcardType t) { + if (s.tag != TYPEVAR || !(s instanceof CapturedType)) + return false; + return isSameWildcard(t, ((CapturedType)s).wildcard); + } + + public boolean isSameWildcard(WildcardType t, Type s) { + if (s.tag != WILDCARD) + return false; + WildcardType w = (WildcardType)s; + return w.kind == t.kind && w.type == t.type; + } + public boolean containsTypeEquivalent(List<Type> ts, List<Type> ss) { while (ts.nonEmpty() && ss.nonEmpty() && containsTypeEquivalent(ts.head, ss.head)) {
27-11-2006

EVALUATION The problem was that containsType does not produce the correct answer for a wildcard and its capture, or two wildcards of the same captured type.
27-11-2006

EVALUATION This is failing again.
17-10-2006

EVALUATION Yep. This was fixed as part of 6268476.
26-01-2006

EVALUATION This must have been fixed by one of my fixes in Mustang b65 or b67.
30-12-2005