-
Bug
-
Resolution: Unresolved
-
P4
-
None
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.)
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.)
- relates to
-
JDK-8054309 5.1.10: Lower-bounded wildcard sometimes maps to its bound in javac
- Open
-
JDK-8054941 4.5: Possibly modify well-formedness restriction for wildcards?
- Open
-
JDK-8154792 Failure to detect malformed parameterized type
- Open
-
JDK-8043351 4.5: Capture to check well-formedness of a parameterized type may be undefined
- Open
-
JDK-8035713 javac, inconsistent inference output for javac8 -source 7
- Closed