United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6365166 javac (generic) unable to resolve methods
JDK-6365166 : javac (generic) unable to resolve methods

Details
Type:
Bug
Submit Date:
2005-12-19
Status:
Closed
Updated Date:
2011-05-18
Project Name:
JDK
Resolved Date:
2011-05-18
Component:
tools
OS:
windows_xp
Sub-Component:
javac
CPU:
x86
Priority:
P5
Resolution:
Fixed
Affected Versions:
5.0
Fixed Versions:

Related Reports
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 :
javac failes to resolve the generic invocation for the methods as detailed in the code segments

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile the code supplied

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
code should compile and run
ACTUAL -
erro produced from javac


ERROR MESSAGES/STACK TRACES THAT OCCUR :

 <L,LF>addOrCreate4(java.lang.Number,L,LF) in NewTest<java.lang.Long,java.lang.Number> cannot be applied to (int,java.util.List<java.lang.Number>,NewTest.ListFactory<java.lang.Number>)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.*;

public class NewTest<A,B> {
    private List<A> toAdd;
    
    public NewTest(List<A> toAdd) {
        this.toAdd = toAdd;
    }
    
    private List<A> getRelated(B b) {
        //some application logic
        //for demo
        return toAdd;
    }
    
    @SuppressWarnings("unchecked")
    public <L extends List<? super A>,LF extends Factory<L>> L addOrCreate4(B b,L l,LF lf) {
        if (l == null) {
            l = lf.create();
        }
        ((List<? super A>)l).addAll(getRelated(b)); //to get round the compiler bug
        return l;
    }
    
    public static class ListFactory<T>  implements Factory<List<T>>{
        public List<T> create() {
            return new ArrayList<T>();
        }
    }
    public static interface Factory<T> {
        public T create();
    }
    
    public static void main(String ... args) {
        ListFactory<Number> lf = new ListFactory<Number>();
        List<Long> longs = new ArrayList<Long>();
        longs.add(new Long(1));
        NewTest<Long,Number> test = new NewTest<Long,Number>(longs);
        
        List<Number> ret4 = null;
        
        ret4 = test.addOrCreate4(1, ret4,lf);
        
    }
}

---------- END SOURCE ----------

                                    

Comments
EVALUATION

This is a capture conversion bug. In particular, during the method call "l.addAll(la)" we have the following situation:

-the type of the receiver is List<? super A> after capture conversion. This yields  the type List<#CAP1>, where the lower bound of #CAP1 is A, while the upper bound of #CAP1 is Object.

-the formal signature of addAll() is addAll(Collection<? extends E>), where E is a type variable of the class Collection<E>.

-the type of the actual argument la is the type of la List<A>.

After having having applied 15.12.2.2 (Applicable method by subtyping) we have that both List.addAll(), Collection.addAll(), ...
So the compiler should apply JLS 15.12.2.5 (Choosing the most specific method). This process consists in finding which of the previously found methods is the most appropriate for the call. This is done by basically ensuring that the formals arguments of the most specific method are subtypes of the formals of the other method.

In this case we have:

m1 = List<#CAP1>.addAll(Collection<? extends #CAP1>)
m2 = Collection<#CAP1>.addAll(Collection<? extends #CAP1>)

So the subtyping test for the only argument of addAll() can be written as follows:

Collection<? extends #CAP1> <: Collection<? extends #CAP1>

Those types seems quite similar but the compiler won't treat them as such. Instead javac goes on and capture the LHS thus causing the subtyping test to fail.
                                     
2008-02-19
SUGGESTED FIX

The problem described in this CR has been solved by CR 6356673
                                     
2008-04-02



Hardware and Software, Engineered to Work Together