Community
Participate
Working Groups
I20041207-0800 The interface java.util.List declares as its last method: List<E> subList(int fromIndex, int toIndex); The type binding of the return type List<E> is currently the same as the type binding of the interface's declaration (see e.g. new ASTView, choose "Add to comparison tray" from context menu of one binding, then select the other one). The return type of method subList(..) should be a parameterized type, not a generic type. (That getJavaElement() is null for the generic binding is bug 80466). Compare to the (correct) parameterized return type binding of method ListIterator<E> listIterator(int index);
Inside the compiler they are the same type. The type of 'this' is the generic type, and thus: List<E> l = this; requires that these be the same type. Now, on DOM AST, they could both be a param type.
I see; it's just strange for clients that class Generic<T> { Generic<T> list= this; Generic<? super T> list2= this; } results in different kinds of bindings.
Philippe, what do you propose for the DOM/AST binding? Right now I use the compiler's bindings.
In fact, it's not just strange, it is wrong. The List<E> in List<E> subList(int fromIndex, int toIndex); is a type reference where E is the type *argument* of the List. In contrast, the binding of the generic type List<E> has E as type *parameter*. This is wrong since E is not declared in the return type.
This bug is causing me trouble when I try to play assignment rules. In the DOM/AST, the bindings for 'this' and 'List<E>' should be parameterized types and not generic types. Is this very difficult or can you do something here?
Philippe, could you please let me know you plan for this one? Right now the DOM/AST is exposing compiler's binding. So fixing this might require fixing the compiler's bindings.
No action planned on compiler end. Generic types are assimilated to parameterized types using their own parameters as arguments. Maybe the DOM spec should clarify these, and likely not refrain from changing this in the future. Markus - the entire compiler relies on this assumption for other reasons, changing this would be quite a lot of work. Now the DOM could hide this, but this feels to late to change this.
Philippe, IMO the DOM ast should provide a view which is consistent with the spec. The example: class Generic<T> { Generic<T> list= this; Generic<? super T> list2= this; } really shows that we have a problem here in the DOM AST which we should fix (from a client point of view it is not understandable why list is a generic type and list2 is a parameterized type). I can understand that it is very late in the game to fix this so a couple of questions: - how risky is this to be fix in the DOM/AST level only ? - Markus, do we already have workaround code in place for this. If not how expensive is it to add this. I am not a fan of specing this and always returning the false answer here. This requires that every client that deals with generic/parameterized types has to be aware of this and has to work around the bug.
I don't think the DOM could survive such a change. It relies a lot on compiler bindings, and provides a 1:1 mapping. A good approach would be to reconsider this in the compiler, but this is not going to occur within 3.1 (and possibly never). I understand the complexity for clients of DOM APIs. One nice characteristics still is that the type of 'this' is the generic type, which wouldn't be the case any longer if generic types were hidden.
The 'this' case might be discussable however for me the list versus list2 case it not. For clients it will never be understandable why one is a parameterized type and one a generic. Markus will look into if we can workaround for 3.1. I would appreciate if Olivier could look into converting this in the DOM world as well. As far as I understand the problem a generic type binding can only occur on the declaration of a type (e.g public class GenericTypes<E> {...} ). All others occurences must be parameterized types. So if we have a generic type binding and it is not the name of a declaration it should be parameterized.
The problem is that there is no creation of compiler's binding during the conversion to DOM bindings. It is a 1:1 mapping. DOM API are calls to compiler's method. There is no way right now to emulate such behavior without getting a support from the compiler's binding.
Can the compiler create both bindings and DOM simply uses the other one ?
I'd rather change the compiler, but this is far too big of a change. Especially after 9 months of surviving in this situation.
No action planned for 3.1, may reconsider later.
Reconsidering for 3.2
All references to a generic type are now parameterized type bindings, no matter where the reference occurs (inside/outside). Tuned various existing tests. Fixed Olivier - would you pls add a specific test for this one ?
*** Bug 107788 has been marked as a duplicate of this bug. ***
Just for the records (i.e. such that I remember when I read this bug again): This fix also has subtle consequences on bindings for members of a type, since 'this' inside a generic type has a parameterized type now. In the example below, - the binding for the declaration of foo() has a getDeclaringClass() with isGenericType() == true, but - the binding for the invocation of method foo() has a getDeclaringClass() with isParameterizedType() == true class G<E> { void foo() {} void use() { foo(); } } The same applies for all members, also e.g. for static methods. Before the fix, the two bindings were identical. The fix for failing clients usually is to compare get{Method|Variable|Type}Declaration() of two bindings.
Added regression test org.eclipse.jdt.core.tests.dom.ASTConverter15Test.test0203
Verified for 3.2 M4 using build I20051213-0010