United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6356673 javac incorrectly generates "reference to <xx> is ambiguous"
JDK-6356673 : javac incorrectly generates "reference to is ambiguous"

Details
Type:
Bug
Submit Date:
2005-11-29
Status:
Closed
Updated Date:
2011-03-08
Project Name:
JDK
Resolved Date:
2011-03-08
Component:
tools
OS:
windows_xp
Sub-Component:
javac
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
5.0,6
Fixed Versions:

Related Reports
Backport:
Backport:
Duplicate:
Relates:

Sub Tasks

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
EVALUATION

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

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

This is failing again.
                                     
2006-10-17
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.
                                     
2006-11-27
SUGGESTED FIX

Webrev of changes: http://sa.sfbay/projects/langtools/bugid_summary.pl?bugid=6356673
See also attachment 6356673.tar.gz.
                                     
2006-11-27
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)) {
                                     
2006-11-27



Hardware and Software, Engineered to Work Together