Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 276252

Summary: [1.5][compiler] Compiler error on sorting generics with java.util.Collections
Product: [Eclipse Project] JDT Reporter: Jan Hoppe <jan.hoppe>
Component: CoreAssignee: Srikanth Sankaran <srikanth_sankaran>
Status: CLOSED WONTFIX QA Contact:
Severity: normal    
Priority: P3 CC: deepak, Olivier_Thomann, philippe_mulet, satyam.kandula, srikanth_sankaran
Version: 3.5   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard: stalebug
Attachments:
Description Flags
Sample Project showing error in synthetic class none

Description Jan Hoppe CLA 2009-05-14 03:17:53 EDT
Created attachment 135747 [details]
Sample Project showing error in synthetic class

Build ID: I20090503-1800

Steps To Reproduce:
1.Create class listed below
2.Works on 3.4.2
3.Error on 3.5M7 (The method sort(List<T>, Comparator<? super T>) in the type Collections is not applicable for the arguments (Vector, Comparator<capture#1-of ? extends ComperatorCheck.A>)	ComperatorCheck.java	/ErrorChecker/src	line 30	Java Problem

This one blocks usage of 3.5 in our Company

More information:
public class ComperatorCheck
{
    class A
    {
        
    }
    
    void compare()
    {
        Vector children = new Vector();
        Comparator<? extends A> comparator = null;
        Collections.sort(children, comparator);

    }
}
Comment 1 Olivier Thomann CLA 2009-05-14 08:58:25 EDT
Compiles fine with javac 1.6 and 7.0.
With 1.6_14 I get:
X.java:10: warning: [unchecked] unchecked conversion
found   : java.util.Vector
required: java.util.List<T>
        Collections.sort(children, comparator);
                         ^
X.java:10: warning: [unchecked] unchecked method invocation: <T>sort(java.util.List<T>,java.util.Comparator<? super T>) in java.util.Collections is applied to (java.util.Vector,java.util.Comparator<capture#31 of ? extends X.A>)
        Collections.sort(children, comparator);
                        ^
Comment 2 Philipe Mulet CLA 2009-05-14 13:04:55 EDT
I would think this code should indeed be accepted.
Comment 3 Kent Johnson CLA 2009-05-14 13:10:17 EDT
Smaller testcase

import java.util.Comparator;

class X {
	<T> void sort(Comparator<? super T> c) {}
	<T> void sort2(Comparator<? extends T> c) {}

	void a(Comparator<?> a) {
		sort(a); // eclipse reports an error that javac doesn't
	}

	void b(Comparator<?> b) {
		sort2(b); // accepted by both
	}
}
Comment 4 Kent Johnson CLA 2009-05-14 13:54:26 EDT
in 3.4.2, only the sort2 call was an error (its not in javac)

now both the sort & sort2 calls cause errors (javac reports a warning on sort)


import java.util.*;

class Y {
	<T> void sort(List<T> list, Comparator<? super T> c) {}
	<T> void sort2(Comparator<? super T> c) {}

	void a(Vector v, Comparator<?> c) {
		sort(v, c);
		sort2(c);
	}
}
Comment 5 Kent Johnson CLA 2009-05-14 14:05:31 EDT
in 3.4.2, we use to infer
  sort(List#RAW, Comparator#RAW)
  sort2(Comparator<? super Object>) 

but now we infer
  sort(List<Object>, Comparator<? super Object>)
  sort2(Comparator<? super Object>)

Comment 6 Kent Johnson CLA 2009-05-15 11:15:37 EDT
Philippe - we differ from javac in all 3 sends of accept1(Comparator<? super T>)

Should Comparator<? super T> be converted to Comparator<?> instead ?


import java.util.*;

class Y {
  <T> void accept1(Comparator<? super T> c) {}
  void accept2(Comparator<?> c) {}
  void accept3(Comparator<? extends Object> c) {}
  void fail(Comparator<? super Object> c) {}

  void a(Comparator<? extends Object> c) {	
    accept1(c); // eclipse fails, we infer Comparator<? super Object>
    accept2(c);
    accept3(c);
    fail(c); // javac rejects since Comparator<? super Object> is not a match
  }
  void b(Comparator<?> c) {
    accept1(c); // eclipse fails, we infer Comparator<? super Object>
    accept2(c);
    accept3(c);
    fail(c); // javac rejects since Comparator<? super Object> is not a match
  }
  void c(Comparator<? extends Y> c) {
    accept1(c); // eclipse fails, we infer Comparator<? super Object>
    accept2(c);
    accept3(c);
    fail(c); // javac rejects since Comparator<? super Object> is not a match
  }
}
Comment 7 Philipe Mulet CLA 2009-05-23 09:34:31 EDT
Re: testcase in comment 0
We do no longer trigger raw conversion for unchecked invocations, as we used to in 3.4.x; and thus matches both the spec expectation (15.12.2.6) and javac, in general.

We do indeed infer #sort(List<Oject>, Comparator<? super Object>); which is also consistent with javac (can be proven by a variation on the testcase, by checking the 
error message when unable to convert from T=Object to int :
import java.util.Comparator;
import java.util.List;
import java.util.Vector;

public class X {
    class A {
    }
    void compare2() {
        Vector children = new Vector();
        Comparator<? extends A> comparator = null;
        int i = sort2(children, comparator);
    }
    static <T> T sort2(List<T> list, Comparator<? super T> c) {  return list.get(0); }
}

We do produce an error during substituted method applicability check, where the compiler does not consider that: Comparator<capture-of-? extends A> is a super type of Comparator<? super Object>
which seems to be a valid diagnosis, as can be checked by simpler testcase, where both javac and Eclipse do complain:

import java.util.*;
public class X {
    class A {
    }
    void foo(Comparator<? super Object> cso) {
    }
    void bar() {
        Comparator<? extends A> comparator = null;
    	foo(comparator);
    }
}
Comment 8 Philipe Mulet CLA 2009-05-23 09:36:31 EDT
erratum:
> ... Comparator<capture-of-? extends A> is a super type of Comparator<? super Object>
should read:
> ... Comparator<capture-of-? extends A> is compatible with Comparator<? super Object>

Comment 9 Philipe Mulet CLA 2009-05-23 09:37:46 EDT
It almost feels that in presence of unchecked method invocation, javac would bypass the applicability check... I know they do bypass the bound checks (against the spec already).
Comment 10 Philipe Mulet CLA 2009-05-23 09:42:34 EDT
Actually, it only bypasses the check when the argument type contains the offending unchecked type param:

e.g. complains for:

public class X {
    class A {}
    <T> void foo(List<T> ls, Comparator<? super Object> cso) {}
    void bar() {
        Comparator<? extends A> comparator = null;
    	foo(new Vector(), comparator);
    }
}

e.g. does NOT complain for (only unchecked warnings) :

public class X {
    class A {}
    <T> void foo(List<T> ls, Comparator<? super T> cst) {}
    void bar() {
        Comparator<? extends A> comparator = null;
    	foo(new Vector(), comparator);
    }
}
Comment 11 Olivier Thomann CLA 2009-08-27 15:54:59 EDT
Targetting 3.6. If a fix is found in time for 3.5.2, we might backport it.
Comment 12 deepak CLA 2009-10-13 23:29:04 EDT
Here's another simple test case that I believe is related to this bug. 

The following works in Eclipse 3.4 but not in 3.5
--------------------------------------
public class Main {
  class Foo implements Comparable {
    @Override
    public int compareTo(Object o) {
      return 0;
    }
  }

  public static void main(String[] args) {
    List<Foo> foo = new ArrayList<Foo>();
    Foo bar = Collections.max(foo); // Error in 3.5
  }
}
--------------------------------------
Changing Foo to the following appeases 3.5 and makes the error go away

class Foo implements Comparable<Object> {
...
}
Comment 13 Srikanth Sankaran CLA 2009-12-03 00:17:52 EST
(In reply to comment #12)
> Here's another simple test case that I believe is related to this bug. 
> 
> The following works in Eclipse 3.4 but not in 3.5
> --------------------------------------
> public class Main {
>   class Foo implements Comparable {
>     @Override
>     public int compareTo(Object o) {
>       return 0;
>     }
>   }
> 
>   public static void main(String[] args) {
>     List<Foo> foo = new ArrayList<Foo>();
>     Foo bar = Collections.max(foo); // Error in 3.5
>   }
> }
> --------------------------------------

This is same as bug#277643 fixed and released into 3.5.2
The issue in comment#0 is still open and is under investigation.
Comment 14 Srikanth Sankaran CLA 2010-05-05 09:00:22 EDT
(In reply to comment #11)
> Targetting 3.6. If a fix is found in time for 3.5.2, we might backport it.

Going to require more time to analyze this. At least the initial
analysis per earlier comments points to a probable javac issue.

Need to retarget to post 3.6
Comment 15 Srikanth Sankaran CLA 2010-05-10 04:00:49 EDT
Retargetting to 3.7. If resolution found in time for 3.6.2, will
make it available for 3.6.2.
Comment 16 Olivier Thomann CLA 2011-04-21 14:03:54 EDT
If we want to address it for 3.7, it has to be done for RC1.
Comment 17 Srikanth Sankaran CLA 2011-05-04 01:10:51 EDT
Sorry, didn't have time to look into this yet as most of
the cycles in the last few months went into Java 7 work.
Now it is too late in the game for 3.7. Postponed to 3.8
Comment 18 Srikanth Sankaran CLA 2012-05-09 21:00:11 EDT
Sorry, need to postpone this as I don't have time in the 3.8 time frame.
Comment 19 Jan Hoppe CLA 2014-05-06 07:12:50 EDT
Problem remains in 4.4M6...
Comment 20 Eclipse Genie CLA 2019-11-08 02:10:48 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.