Bug 108783 - [1.5][compiler] Runnable masks Iterable interface in bounds
Summary: [1.5][compiler] Runnable masks Iterable interface in bounds
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1.1   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 3.1.1   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-09-05 06:25 EDT by Maxime Daniel CLA
Modified: 2005-09-26 11:33 EDT (History)
1 user (show)

See Also:


Attachments
Test case (1.55 KB, patch)
2005-09-05 06:38 EDT, Maxime Daniel CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Maxime Daniel CLA 2005-09-05 06:25:09 EDT
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.)
Comment 1 Maxime Daniel CLA 2005-09-05 06:38:59 EDT
Created attachment 26827 [details]
Test case

Moved test case to test812.
Comment 2 Olivier Thomann CLA 2005-09-06 14:38:57 EDT
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.
Comment 3 Olivier Thomann CLA 2005-09-06 14:44:41 EDT
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);
	}
}
Comment 4 Olivier Thomann CLA 2005-09-06 15:16:56 EDT
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.
Comment 5 Philipe Mulet CLA 2005-09-08 08:37:20 EDT
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.
Comment 6 Philipe Mulet CLA 2005-09-09 13:19:24 EDT
Forked a separate bug for cast insertions.
Comment 7 Philipe Mulet CLA 2005-09-09 13:20:46 EDT
Added ForeachStatementTest#test033-035.
Fixed (only fixing the #iterator() invocation declaring class in descriptor).

Olivier - can you pls enable your tests as well ?
Comment 8 Philipe Mulet CLA 2005-09-09 13:24:59 EDT
Separate bug for cast insertions is bug 109098
Comment 9 David Audel CLA 2005-09-21 10:48:50 EDT
Verified in I20050921-0010 for 3.2M2
Comment 10 Olivier Thomann CLA 2005-09-26 11:33:41 EDT
Verified for 3.1.1 using M20050923-1430.