Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6278587
Votes 2
Synopsis Compiler fails to infer correct type for under-constrained type variables
Category java:compiler
Reported Against
Release Fixed 7(b05)
State 9-Fix Failed, bug
Priority: 3-Medium
Related Bugs 6284158 , 6468384 , 6491939 , 6498829 , 6536404 , 6559165 , 6570321 , 6650759
Submit Date 01-JUN-2005
Description
This program doesn't compile

import java.util.*;

public class TestGenerics {
 
	/**Subclasses are parameterized by their own type*/
	private static abstract class SelfType<T extends SelfType<T>>{
		public abstract T getThis();
	}
 
	/**Supertype inherits directly from the parameterized SelfType*/
	private static class SuperType extends SelfType<SuperType>{
		@Override
		public SuperType getThis(){
			return this;
		}
	}
 
	/**Subtype inherits indirectly from the parameterized SelfType*/
	private static class SubType extends SuperType{}
 
	/**Creates a list containing a single SelfType*/
	public static <T extends SelfType<T>> List<T> makeSingletonList(T t){
		return Collections.singletonList(t);
	}
 
	/**
	 * Creates a list containing a single SelfType, allowing the list's
	 * element-type to be a supertype of the type of its single element
	 */
	public static <T extends SelfType<T>,S extends T> List<T> makeSingletonList2(S s){
		return Collections.singletonList((T)s);
	}
 
	public static void main(String[] args){
		/*making lists of super types works fine ...*/
		makeSingletonList(new SuperType());
		List<SuperType> lsup = makeSingletonList(new SuperType());
 
		/*but we can't make a list of sub types; seems weird ...*/
		List<SubType> lsub = makeSingletonList(new SubType()); //ERROR
		/*can't even call it w/o assigning the return value:*/
		makeSingletonList(new SubType()); //ERROR
 
 
		/*so instead, we should be able to make lists of super type containing sub type elements*/
		makeSingletonList2(new SubType()); //ERROR
		/*even if we assign the return value:*/
		lsup = makeSingletonList2(new SubType()); // ERROR (eclipse is okay with this though)
		/*this still doesn't work either:*/
		lsub = makeSingletonList2(new SubType()); // ERROR
 
		/*we can make lists of super type this way though*/
		makeSingletonList2(new SuperType()); // (eclipse doesn't like this though)
		/*also ok if we assign the return value*/
		lsup = makeSingletonList2(new SuperType());
	}
}

See http://forum.java.sun.com/thread.jspa?threadID=632009&tstart=0

  xxxxx@xxxxx   2005-06-01 00:42:45 GMT
Work Around
Work around for the reduced case:

D<B> d = this.<B,C>m(c);

Work around for the original example:

makeSingletonList(new SuperType());
List<SuperType> lsup = makeSingletonList(new SuperType());

// This can't be made to work, List<SuperType> is not
// a subtype of List<SubType>
List<SubType> lsub = TestGenerics.<SuperType>makeSingletonList(new SubType());

TestGenerics.<SuperType>makeSingletonList(new SubType());
TestGenerics.<SuperType,SubType>makeSingletonList2(new SubType());
lsup = TestGenerics.<SuperType,SubType>makeSingletonList2(new SubType());

// Can't work, see above
lsub = TestGenerics.<SuperType,SubType>makeSingletonList2(new SubType());

  xxxxx@xxxxx   2005-06-12 09:05:59 GMT
Evaluation
Let's examine each "error":

List<SubType> lsub = makeSingletonList(new SubType());

According to JLS 3rd Ed. (15.12.2.2 Phase 1: Identify
Matching Arity Methods Applicable by Subtyping) inference
is started with the initial constraint SubType << T.
This infers the type SubType for T.  In JLS lingo, this
gives U1 = SubType and S1 = SubType.  In order for the
method to be applicable, A1 must be a subtype of
S1 which is trivially true (SubType is a subtype of itself).

However, the inferred type U1 must also be a subtype
of B1[R1=U1, ...] which translates to:
SubType must be a subtype of SelfType<SubType> which
it isn't.

The same analysis holds for
makeSingletonList(new SubType());

Next is
makeSingletonList2(new SubType());

Here the inference is simpler, the type inferred
for S is SubType, but T is under constrained, so
Object is inferred for T.  However, Object is not
a subtype of SelfType<Object> why the method
invocation fails.

Next is
lsup = makeSingletonList2(new SubType());

Here again, T is under constrained but there is an
expected type, so the type inferred for T should
be SuperType which is indeed a subtype of SelfType<SuperType>.

This is a bug.

Lastly, consider
lsub = makeSingletonList2(new SubType());

Again, T is under constrained so the expected type
is considered and SubType is inferred for T.  However,
SubType is not a subtype of SelfType<SubType>.

In summary, there is one bug here and it can be reduced to this:

abstract class Simple {
    interface A<T extends A<T>> {}
    interface B extends A<B> {}
    interface C extends B {}
    interface D<T> {}
    abstract <T extends A<T>, S extends T> D<T> m(S s);
    {
	C c = null;
	D<B> d = m(c);
    }
}

  xxxxx@xxxxx   2005-06-12 09:05:58 GMT
The fix of this bug caused a significant amount of compatibility issues (see 6650759, 6559165, 6536404 and related CRs).
Posted Date : 2009-03-03 17:36:42.0
Comments
  
  Include a link with my name & email   

Submitted On 10-JUN-2005
mmchenry@carnegielearning.com
This bug also submitted to the eclipse project:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=98538



PLEASE NOTE: JDK6 is formerly known as Project Mustang