JDK-6732484 : Bound error on wildcard code
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2008-08-01
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b40Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
This somewhat confusing code result in a bound error. It passed as of recent builds.
------FBoundedColorPoint.java-----------------
public class FBoundedColorPoint
{

class AbstractPoint<T extends AbstractPoint<T>>     {
        int x, y;
        boolean equals(T that)  { return (this.x == that.x) && (this.y == that.y); }
}

class Point extends AbstractPoint<Point>         {    }

    public FBoundedColorPoint()         {
                AbstractPoint<? super Point> con;   // <<pass>>
    }
}
---------------
This test case I though was in the regression test set, so maybe it was removed(?) and so I gave it rather low priority. The error message  is:

FBoundedColorPoint.java:12: type parameter capture#716 of ? super FBoundedColorPoint.Point is not within its bound
                AbstractPoint<? super Point> con;   // <<pass>>
                                      ^
1 error

Comments
EVALUATION I'm evaluating some technique for loosening JLS 4.5 a bit. Applying straight subtyping after capture conversion is not that good as I first thought and this bug confirms this feeling. Not applying capture conversion is bad either, because the compiler could end up in replacing type variables with wildcards in the type var bound to be checked. Moreover there are other problems related to the lack of capture conversion when checking for bound conformance (see 6526842). The bottom line is that we should preserve capture conversion, but we should also try to mimick the old, non-captured logic where possible (e.g. by adding a new form of subtyping - soft subtyping - that allows javac to be more flexible when dealing with captured type-variables). The underlying idea behind the 'old logic' is to allow all types that have some kind of non-empty generic instantiation. In this respect, the type AbstractPoint<? super Point> should be allowed as there is at least one instantiation that is assignable to that type - namely AbstractPoint<Point>.Note that AbstractPoint<Point> respects all the constraints (Point is a subtype of [T:=Point]AbstractPoint<T>). Rejecting this program only because subtyping rules cannot prove that the type is correct sounds a bit harsh (even if - in principle - that type could virtually be replaced by AbstractPoint<Point>, as this is the only instantiation contained by AbstractPoint<? super Point>).
09-09-2008

SUGGESTED FIX A webrev of this fix is available at the following URL: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/6508d7e812e1
01-08-2008

EVALUATION This bug has been introduced since 7 b32 as a result of the fix for 6651719. That fix was quite critical and I was kinda expecting failures of this kind even though the patched compiler passed all the JCK tests. Let's look at the problem: when validating the type declaration for: AbstractPoint<? super Point> javac executes the following steps: 1) capture AbstractPoint<? super Point>, the result is AbstractPoint<X>, where Point <: X 2) substitute X for T in the declared bound of T as defined in AbstractPoint. Since the bound is AbstractPoint<T>, the result of the type-substitution is AsbtractPoint<X> 3) issue the following subtyping test: lower-bound(X) <: upper-bound([X/T]T) which is equivalent to: Point <: AbstractPoint<X> AbstractPoint<Point> <: AbstractPoint<X> At this point there's no way of prooving the correctness of this subtyping test, as the method Types.notSoftSubtypes has some issues involving captured types appearing in recursive fbounds - this issue is addressed by CR 6548436. Without that fix it's almost impossible to accept this code, as, surprisingly, no subtyping rule in the JLS justifies the subtyping between the two terms AbstractPoint<point> and AbstractPoint<X>, where Point <: X
01-08-2008