Bug 100619 - [1.5][compiler] Incorrect duplicate bound diagnosis
Summary: [1.5][compiler] Incorrect duplicate bound diagnosis
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.1.1   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-06-17 13:06 EDT by Philipe Mulet CLA
Modified: 2005-11-15 08:43 EST (History)
1 user (show)

See Also:


Attachments
Patch for JDTCore (8.31 KB, patch)
2005-06-21 09:23 EDT, Philipe Mulet CLA
no flags Details | Diff
Patch for compiler tests (4.00 KB, patch)
2005-06-21 09:23 EDT, Philipe Mulet CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Philipe Mulet CLA 2005-06-17 13:06:20 EDT
RC3 candidate

The following code complains incorrectly about a duplicate bound T :

public class X {
	<T extends Runnable, U extends Runnable & T>  T foo() { return null; }
}
Comment 1 Philipe Mulet CLA 2005-06-21 07:14:18 EDT
The bound check diagnosis is incorrectly erasing supertypes, and thus thinks a
type variable bound (T) means Runnable, and incorrectly thinks it is a duplicate.

The type variable hierarchy computation should mimic the normal superinterfaces
connection (for types) and also notice situations like:

public class X {
	<T extends Runnable, U extends Runnable & T>  T foo1() { return null; }
	<T extends Y<Object>, U extends Z & T>  T foo2() { return null; }
	<T extends Y<Object>, U extends T & Z>  T foo3() { return null; }
	<T extends Y<Object>, U extends W & Z>  T foo4() { return null; }
}

interface Y<T> {}
interface Z extends Y<String> {}
interface W extends Y<Object> {}

foo1 --> wrong as T doesn't act as an interface in formal bound
foo2 --> OK (but javac rejects it incorrectly)
foo3 --> incompatible supertype (RC3 doesn't notice)
foo4 --> incompatible supertype (RC3 doesn't notice)
Comment 2 Philipe Mulet CLA 2005-06-21 09:05:51 EDT
Fix has 2 parts:
1. stop tagging as interface a type variable with interface first formal bound.
2. reuse check from standard superinterfaces computation which detects
collisions and duplicates correctly. Also get rid of unnecessary problem
reporting code, since it reuses problem reporting from normal hierarchy computation.

----------
1. ERROR in X.java
 (at line 2)
	<T extends Runnable, U extends Runnable & T>  T foo1() { return null; }
	                                          ^
The type T is not an interface; it cannot be specified as a bounded parameter
----------
2. ERROR in X.java
 (at line 3)
	<T extends Y<Object>, U extends Z & T>  T foo2() { return null; }
	                                    ^
The type T is not an interface; it cannot be specified as a bounded parameter
----------
3. ERROR in X.java
 (at line 5)
	<T extends Y<Object>, U extends W & Z>  T foo4() { return null; }
	                                    ^
The interface Y cannot be implemented more than once with different arguments:
Y<String> and Y<Object>
----------
Comment 3 Philipe Mulet CLA 2005-06-21 09:22:43 EDT
Added GenericTypeTest#test768, updated test429 to reflect error message
improvements.
Comment 4 Philipe Mulet CLA 2005-06-21 09:23:09 EDT
Created attachment 23614 [details]
Patch for JDTCore
Comment 5 Philipe Mulet CLA 2005-06-21 09:23:38 EDT
Created attachment 23615 [details]
Patch for compiler tests
Comment 6 Philipe Mulet CLA 2005-06-21 10:29:19 EDT
At this stage of the game, API changes are forbidden. So IProblem should remain
untouched (with unused constant for obsoleted problem). This constant is unused
by Eclipse SDK (only user would be quickfix anyway), but stil...
Comment 7 Kent Johnson CLA 2005-06-21 13:58:11 EDT
Fix looks good, but this case is unlikely to appear in many cases.

I would postpone until 3.1.1
Comment 8 Philipe Mulet CLA 2005-06-29 04:11:32 EDT
Fixed in 3.1 maintenance branch
Comment 9 Maxime Daniel CLA 2005-08-09 09:29:08 EDT
Verified in 3.2 M1 with build I20050808-2000.
Note that we now have a behavior comparable to javac's for foo2 - the type
parameter is not accepted in place of an interface, even though it extends
an interface.
Comment 10 David Audel CLA 2005-09-26 09:57:13 EDT
Verified using M20050923-1430 for 3.1.1
Comment 11 Steven Coco CLA 2005-11-14 23:07:50 EST
(In reply to comment #10)
> Verified using M20050923-1430 for 3.1.1
> Note that we now have a behavior comparable to javac's for foo2 - the type
> parameter is not accepted in place of an interface, even though it extends
> an interface.

Hello.


I stumbled over this while researching a problem of my own (with javac).

I am currently under the impression that these incantations are not legal:

  a. <T extends Runnable, U extends Runnable & T>...
  b. <T extends Y<Object>, U extends Z & T>...

The language spec (section 4.4) states that the only legal place for a type
variable to appear in a bound is in the first position -- as in: <T extends
Runnable, U extends T & Runnable>.

Perhaps you have other knowledge though.  I have not reached a conclusion on my
difficulty.

Good luck.


Ciao,
Steven Coco.
Comment 12 Steven Coco CLA 2005-11-14 23:46:30 EST
Forgive my clutter.


I seem to have figured it out:  If the type variable is specified, then this can
be the only bound.  The additional bounds are not allowed in this case.

The language spec is worded too technically at this point.

Have you got it worked out?

If you'd like other references, in Gilad Bracha's generics tutorial, we see the
use of <T extends Object & Comparable<? super T>> but not one with a type
variable and additional bounds:

http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

And this reference contains a reference to this point as well:

http://pag.csail.mit.edu/~adonovan/hacks/generic-java/


Thanks...
Steev Coco.
Comment 13 Philipe Mulet CLA 2005-11-15 08:43:28 EST
Pls see bug 106466, this is a slightly different issue.