Bug 182192

Summary: [1.5] [compiler] loss of generic type information in inner class
Product: [Eclipse Project] JDT Reporter: Jason Rogers <jason>
Component: CoreAssignee: Philipe Mulet <philippe_mulet>
Status: VERIFIED WONTFIX QA Contact:
Severity: normal    
Priority: P3    
Version: 3.3   
Target Milestone: 3.3 M7   
Hardware: PC   
OS: Linux   
Whiteboard:

Description Jason Rogers CLA 2007-04-12 14:13:35 EDT
Build ID: I20070323-1616

Steps To Reproduce:
1. See code in the "More information" section.

In the example, the line "Map.Entry<String, String> entry : myMap().entrySet()" gives the following error: "Type mismatch: cannot convert from element type Object to Map.Entry<String,String>".

I could be wrong but this smells like a bug (the cream-filled, crunchy kind).  The generic nature of "myMap" has nothing to do with the generic nature of the enclosing class nor of the inner class.  The error is fixed if you change the extends clause of the inner class to include the generic markup (eg. "extends GenericsBugInEclipse<T>" instead of "extends GenericsBugInEclipse").

This happens in a 3.2 build as well.

More information:
import java.util.HashMap;
import java.util.Map;

public class GenericsBugInEclipse<T> {
	
	private final Map<String, String> myMap;
	private final T theGenericThing;
	
	private GenericsBugInEclipse(T something) {
		this.myMap = new HashMap<String, String>();
		this.theGenericThing = something;
	}
	
    public static class InnerClassThatShowsBug extends GenericsBugInEclipse {
    	public InnerClassThatShowsBug() {
    		super(null);
		}
    	
    	public void printMap() {
    		for (Map.Entry<String, String> entry : myMap().entrySet()) {
				System.out.println(entry.getKey() + " => " + entry.getValue());
			}
    	}
    }
    
    protected Map<String, String> myMap() {
    	return myMap;
	}
}
Comment 1 Philipe Mulet CLA 2007-04-13 10:46:05 EDT
Unfortunately, this is working as designed. Javac 1.5 and 1.6 both report the same error as we do.

This is a consequence of using a raw supertype. The raw conversion is applied to all non-static member signatures, even if they weren't referring to the type parameter T itself. In your case, the #getMap() method from raw supertype as Map (raw) as its return type, instead of Map<String,String>.

i.e. blame the spec.
Comment 2 Philipe Mulet CLA 2007-04-13 10:53:35 EDT
Added GenericTypeTest#test1124
Comment 3 Jason Rogers CLA 2007-04-13 13:24:15 EDT
OK, thanks for investigating though and for the explanation.
Comment 4 Jason Rogers CLA 2007-04-13 13:25:06 EDT
OK, thanks for investigating and offering up the explanation.  I thus blame the spec!
Comment 5 Olivier Thomann CLA 2007-04-27 21:08:26 EDT
Verified for 3.3M7