Bug 286228 - [1.5][compiler] Generics inconsistencies possible regression
Summary: [1.5][compiler] Generics inconsistencies possible regression
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.5   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 3.6 M3   Edit
Assignee: Kent Johnson CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-08-11 08:21 EDT by John CLA
Modified: 2009-10-27 07:02 EDT (History)
3 users (show)

See Also:


Attachments
generics test case (2.52 KB, text/plain)
2009-08-11 08:21 EDT, John CLA
no flags Details
Proposed patch and testcase (3.79 KB, patch)
2009-10-07 14:04 EDT, Kent Johnson CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John CLA 2009-08-11 08:21:51 EDT
Created attachment 144025 [details]
generics test case

Please check the attached test cases. Release 3.5 of ECJ no longer accepts some generified code that 3.4.1 had previously accepted. Additionally, both 3.4.1 and 3.5 reject code for different reasons whereas javac 1.6.0_16 accepts it in either case.
Comment 1 Kent Johnson CLA 2009-09-03 13:08:59 EDT
I get 2 errors from javac 1.7 (build 1.7.0-ea-b69), but no errors from 1.6 or 1.5.


69: reference to set is ambiguous, both method set(S<T#1>) in SS and method set(S<T#2>) in SI match
                            t.set(null);
                             ^
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in interface SS
    T#2 extends I declared in interface SI
83: reference to set is ambiguous, both method set(S<T#1>) in SS and method set(S<T#2>) in SI match
                            t.set(null);
                             ^
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in interface SS
    T#2 extends I declared in interface SI
2 errors
Comment 2 Kent Johnson CLA 2009-10-06 16:01:11 EDT
Trying to reduce the testcase, found this testcase that we should hold onto :


interface I {}
interface S<T> {}
interface SI<T extends I> { void set(S<T> s); }

class B<T extends SI<? extends I>> {
	public void set(T t, S<I> s) {
		t.set(s); // fails in eclipse & 1.6/1.7
		t.set(null); // passes in eclipse & 1.6/1.7
	}
}


/*
IN 1.6 :
line 8: set(S<capture#74 of ? extends I>) in SI<capture#74 of ? extends I> cannot be applied to (S<I>)
                t.set(s); // fails in eclipse & 1.6/1.7
                 ^
1 error

IN 1.7 :
line 8: method set in interface SI<T> cannot be applied to given types
                t.set(s); // fails in eclipse & 1.6/1.7
                 ^
  required: S<CAP#1>
  found: S<I>
  where T is a type-variable:
    T extends I declared in interface SI
  where CAP#1 is a fresh type-variable:
    CAP#1 extends I from capture of ? extends I
1 error
*/
Comment 3 Kent Johnson CLA 2009-10-06 16:17:39 EDT
javac 1.7 compiles this case without error :

interface I {}
interface S<T> { void set(T t); }
interface GS<T extends I> extends SI<T> {}
interface F<T extends GS<? extends I>> {}

interface SS<T> extends S<S<T>> { void set(S<T> s); }
interface SI<T extends I> extends SS<T> { void set(S<T> s); }

class B<T extends GS<? extends I> & F<T>> implements GS<I>  {
	T t;
	public void set(S<I> s) {
		t.set(s);
		//t.set(null); // fails in 1.7
	}
}


BUT if SI is replaced with :

interface SI<T extends I> { void set(S<T> s); }

then javac 1.7 reports :

method set in interface SI<T> cannot be applied to given types
                t.set(s);
                 ^
  required: S<CAP#1>
  found: S<I>
  where T is a type-variable:
    T extends I declared in interface SI
  where CAP#1 is a fresh type-variable:
    CAP#1 extends I from capture of ? extends I
1 error


I find it surprising that the case should work because SI extends SS, but it doesn't work when SI does not.
Comment 4 Kent Johnson CLA 2009-10-07 14:00:11 EDT
I have a fix for the problem in interface Test1 of the attached test case.

But for Test2, I'm not convinced that eclipse has a bug.

Using this case :

interface I {}
interface S<T> { void foo(T t); }
interface SS<T> extends S<S<T>> { }

interface D<T extends SS<? extends I>> {}

class X<T extends SS<? extends I> & D<T>> {
    void test(T t, S<I> s) {  t.foo(s); } // only fails in eclipse
}

class Y<T extends SS<? extends I>> {
    void test(T t, S<I> s) {  t.foo(s); } // fails in javac 6 & 7, and eclipse
}


javac 7 reports :

X.java:12: method foo in interface S<T> cannot be applied to given types
    void test(T t, S<I> s) {  t.foo(s); } // fails in javac 6 & 7, and eclipse
                               ^
  required: S<CAP#1>
  found: S<I>
  where T is a type-variable:
    T extends Object declared in interface S
  where CAP#1 is a fresh type-variable:
    CAP#1 extends I from capture of ? extends I
1 error


javac 6 reports :

X.java:12: foo(S<capture#935 of ? extends I>) in S<S<capture#935 of ? exte
nds I>> cannot be applied to (S<I>)
    void test(T t, S<I> s) {  t.foo(s); } // fails in javac 6 & 7, and eclipse
                               ^
1 error


eclipse reports 2 errors which I believe are justified.
Comment 5 Kent Johnson CLA 2009-10-07 14:04:53 EDT
Created attachment 149016 [details]
Proposed patch and testcase

Fix for case in Test1
Comment 6 Kent Johnson CLA 2009-10-08 10:10:00 EDT
Sent the case in comment 4 to Sun (ie. interface Test2) & they agree that its their bug.

Its similar to http://bugs.sun.com/view_bug.do?bug_id=6738538


Released fix for the first case to HEAD for 3.6M3
Comment 7 Srikanth Sankaran CLA 2009-10-27 07:02:34 EDT
Verified for 3.6M3 using build I20091025-2000