JDK-8054937 : 5.1.10: Fresh capture variables sometimes can't conform to bounds
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2014-08-12
  • Updated: 2016-04-20
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.
Other
tbd_majorUnresolved
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Given the following declarations:

abstract class Animal<T extends Animal<T>> {
  public abstract T bestFriend();
  public abstract Iterable<T> friends();
}
abstract class Dog extends Animal<Dog> {}

The capture of the following is specified to trigger a compiler error, per 5.1.10:

Animal<? extends Dog> a; // bound of capture var is glb(Dog, Animal<CAP>)

"It is a compile-time error if, for any two classes (not interfaces) Vi and Vj, Vi is
not a subclass of Vj or vice versa."

Actual javac behavior is to allow it, producing (apparently) an intersection of two different class types, 'Dog & Animal<CAP>'.  These leads to arbitrary implementation-specific type checking behavior when members are looked up, e.g., in:

a.bestFriend().friends()

Two possible resolutions:

1) Enhance capture so that it does not produce an intersection of different class types, for example by inferring that 'capture(Animal<? extends Dog>) = Animal<Dog>' (because we know that a type like Animal<Poodle> is not in bounds).

2) Decide that the type Animal<? extends Dog> is malformed and require javac to enforce the restriction.

(Whether the conclusion is (1) or (2), similar reasoning could apply in the case of a final class, like Class<? extends String>.  However, in that case there's nothing wrong with simply allowing the type as is without any special accommodations.)