-
Bug
-
Resolution: Unresolved
-
P4
-
5.0, 7, 8
At issue is the definition of members of an intersection (and, thus, a type variable) (4.9). If you squint, you might see an implicit assertion, sometimes enforced by the compiler, that the imaginary class declaration we use to model membership must be well-formed. If inherited methods clash in certain ways, for example, an error occurs. (However, some checks, such as the requirement that a subclass make an explicit call to super() if the superclass doesn't have a no-arg constructor, are not enforced.)
If it is our intent that the imaginary class be strictly well-formed, the spec needs to be clear about it. If not, the spec needs to outline exactly what assertions must be made about the imaginary class (or abandon the imaginary class crutch and just describe the assertions directly).
In my opinion, the rule should be much more forgiving than those for class declarations: unless we can prove that no witness can exist for an intersection, we should assume it does exist, and not complain. This may mean we have fewer guarantees about membership than we thought, for things like choosing the return type of a method invocation (15.12.2.5). But these guarantees, like an assumption that there always exists a most-specific return type, are illusory anyway: parameterized types don't have the guarantees that simple classes do, and we can't enforce the guarantees in non-Java class files. (I ran into this when trying to reason about functional interface members.)
To illustrate:
class TvarAccess {
/*** Declarations ***/
static abstract class A {
protected abstract String foo();
protected String bar() { return "bar"; }
protected abstract Object clone();
}
interface Foo { public String foo(); }
interface Bar { public String bar(); }
interface PublicClone { public Object clone(); }
// Witness for A&Foo, A&Bar, A&PublicClone, Object&PublicClone
static class C extends A implements Foo, Bar, PublicClone {
public String foo() { return "foo"; }
public String bar() { return "bar"; }
public Object clone() { return this; }
}
interface ReadableFactory {
Readable make();
}
interface CloseableFactory {
java.io.Closeable make();
}
// Witness for ReadableFactory&CloseableFactory
interface ReaderFactory extends ReadableFactory, CloseableFactory {
java.io.Reader make();
}
class RequiresSuperCall {
public RequiresSuperCall(boolean arg) {}
}
// Witness for T extends RequiresSuperCall
class D extends RequiresSuperCall {
public D() { super(true); }
}
/*** Tests ***/
// No error for tvar in javac 7
public <T extends A & Foo> String testMethod1(T arg) {
return arg.foo();
}
// ERROR for tvar in javac 7
public <T extends A & Bar> String testMethod2(T arg) {
return arg.foo();
}
// ERROR for tvar in javac 7
public <T extends A & PublicClone> void testMethod3(T arg) {
arg.clone();
}
// ERROR for tvar in javac 7
public <T extends Object & PublicClone> void testMethod4(T arg) { // error
arg.clone();
}
// ERROR for tvar in javac 7
public <T extends ReadableFactory & CloseableFactory> void testMethod5(T arg) {
arg.make(); // ERROR in javac 7: ambiguous method
}
// No error for tvar in javac 7
public <T extends RequiresSuperCall> void testMethod6(T arg) {
}
}
- blocks
-
JDK-8145978 Javac fails to compile valid program with intersection type containing clone()
- Open
- duplicates
-
JDK-8146964 Unrelated defaults inheritance error for type variables
- Closed
-
JDK-8186643 Compiler error on generic intersection type declaration with two similar interfaces, one with a default implementation
- Closed
- relates to
-
JDK-7030833 4.9: Missing well-formedness rules for type variable bound
- Open
-
JDK-8177716 Type inference broken with Interfaces
- Closed
-
JDK-7111664 javac behavior and reported bug questionable
- Closed
-
JDK-6644562 4.9: Simplify membership of single-bound intersection types
- Open
-
JDK-8269121 Type inference bug with method references
- Open
-
JDK-8027386 Compiler regression error on multi-level abstract generic class with intersection types
- Open
-
JDK-6946211 Multiple generic types cause weaker access privileges error on clone()
- Closed