JDK-6729401 : Compiler error when using F-bounded generics with free type variables
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2008-07-24
  • Updated: 2012-01-13
  • Resolved: 2012-01-13
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 b48Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)
javac 1.6.0


ADDITIONAL OS VERSION INFORMATION :
Linux toth 2.6.15-52-386 #1 PREEMPT Mon Jun 9 17:24:46 UTC 2008 i686 GNU/Linux
a

A DESCRIPTION OF THE PROBLEM :
Running javac on the attached program causes a type error.  It appears to be caused by the occurrence of "U" in the generic declaration "<B extends Bar<U,B>>" being treated as a binding occurrence rather than as a free occurrence, thus causing the unification of V with itself in "x.<Y>bar(y)" to fail.  If U and V are removed, the problem goes away.  If the upper bound on B is removed, the problem goes away.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
javac the attached code, note type error.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Successful compilation.
ACTUAL -
Type error.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Test.java:5: <B>bar(Bar<V,B>) in Bar<V,X> cannot be applied to <Y>(Bar<V,Y>)
    void foo() { x.<Y>bar(y); }
                  ^


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class Foo<V,X extends Bar<V,X>,Y extends Bar<V,Y>> {

    Bar<V,X> x;
    Bar<V,Y> y;
    void foo() { x.<Y>bar(y); }

}

interface Bar<U,A> {
    <B extends Bar<U,B>> void bar(Bar<U,B> x);
}


---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
The version of javac distributed with eclipse does not appear to have this bug.

Comments
SUGGESTED FIX A webrev of this fix is available at the following URL http://hg.openjdk.java.net/jdk7/tl/langtools/rev/79f2f2c7d846
29-01-2009

EVALUATION This is a bug in type-variable substitution. In order to determine the exact type of the invoked method we should apply two steps: 1) Method Bar<U,A>.bar(U,B) is accessed as member of type Bar<V, X>; this yields the following method type: [U:=V]bar(U,B) = Bar<V,X>.bar(Bar<V,B>) 2) Another step is to be applied since B is to be substituted with the actual type argument X: [B:=X]bar(V,B) = Bar<V,X>.bar(Bar<V,X>) Since the above method is called with an argument whose type is exactly Bar<V,X>, the method call is perfectly legal. On the other hand, javac rejects this method call because of a failure of the bound check - but this is a bug since the actual type argument satisfies the declared bound of B: X <: [B:=X, U:=V]Bar<U,B> = Bar<V,X> ub(X) = Bar<V,X> <: Bar<V,X> ok The problem is that javac is seeing two different instances of the same type-variable type B: X <: [B#2:=X, U:=V]Bar<U,B#1> = Bar<V,B#1> ub(X) = Bar<V,X> <: Bar<V,B#1> no because B#1 != X The additional type-variable is generated during step 1) - accessing <B>bar() as a member of Bar<V,X> changes the declared bound of the method type variable B (from Bar<U,B> to Bar<V,B>). Since javac detects that the variable's bound has changed, it creates a copy B#2 of the original type variable with the new bound as declared bound. The problem is that the new variable still refers to the old type-variable through its new bound: the bound of B#2 in fact is (after substitution) Bar<V,B#1>, where B#1 denotes the old type-variable. This causes the compiler failure.
21-01-2009