Community
Participate
Working Groups
The following code should print: a b on the standard output stream. Instead, we get an error: class file for X.java: java.lang.NoSuchMethodError: java.lang.Runnable.iterator()Ljava/util/Iterator; at X.foo(X.java:7) at X.main(X.java:17) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ... Source file: import java.util.Arrays; import java.util.Iterator; import java.util.List; public class X implements Iterable<String>, Runnable { public <T extends Runnable & Iterable<String>> void foo(T t) { for (String s : t) System.out.println(s); } public void run() { /* */ } private List<String> list = Arrays.asList(new String[] { "a", "b" }); public Iterator<String> iterator() { return this.list.iterator(); } public static void main(String... args) { X x = new X(); x.foo(x); } } (Prepared test case GenericTypeTest#test810, tested against 3.1 maintenance branch today.)
Created attachment 26827 [details] Test case Moved test case to test812.
The bug comes from the line 183: final TypeBinding collectionTypeBinding = collection.resolvedType.erasure(); This returns the first bound of the type variable. The type variable is: <T extends java.lang.Runnable & Iterable<java.lang.String>> We should return the part that is compatible with java.lang.Iterable.
In this case, the declaring class of the iterator() call should be java.util.ArrayList. import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.ArrayList; public class X { public static <T extends ArrayList<String>> void foo(T t) { for (String s : t) System.out.print(s); } private static ArrayList<String> list = new ArrayList<String>(); static { list.addAll(Arrays.asList(new String[] { "a", "b" })); } public static void main(String... args) { foo(list); } }
Added disabled regression tests in org.eclipse.jdt.core.tests.compiler.regression.ForeachStatementTest. _test033 and _test034. Once this is fixed, we should add a comparison of the disassembled code for the method foo() in order to check the declaring class of the iterator() call.
There is more to it. We should also insert a generic cast to Iterable, and use Iterable as the declaring class when the erasure isn't a good match.
Forked a separate bug for cast insertions.
Added ForeachStatementTest#test033-035. Fixed (only fixing the #iterator() invocation declaring class in descriptor). Olivier - can you pls enable your tests as well ?
Separate bug for cast insertions is bug 109098
Verified in I20050921-0010 for 3.2M2
Verified for 3.1.1 using M20050923-1430.