JDK-4949438 : 4.5: When are wildcards "the same"?
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 5.0,7,8
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2003-11-05
  • Updated: 2024-04-12
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
tbdUnresolved
Related Reports
Relates :  
Relates :  
Description
The following shows that javac is inconsistent in determining
which overriders are allowed:

class Box<T extends Number> {}

class T1 { // works
    static class A {
        void f(Box<?> box) {}
    }
    static class B extends A {
        void f(Box<? extends Object> box) {}
    }
}

class T2 { // works
    static class A {
        void f(Box<?> box) {}
    }
    static class B extends A {
        void f(Box<? extends Number> box) {}
    }
}

class T3 { // works
    static class A {
        void f(Box<? extends Object> box) {}
    }
    static class B extends A {
        void f(Box<?> box) {}
    }
}

class T4 { // works
    static class A {
        void f(Box<? extends Number> box) {}
    }
    static class B extends A {
        void f(Box<?> box) {}
    }
}

class T5 { // fails
    static class A {
        void f(Box<? extends Object> box) {}
    }
    static class B extends A {
        void f(Box<? extends Number> box) {}
    }
}

Comments
The underlying question here: when are wildcards considered "the same"? 4.3.4 defines "same" strictly (but doesn't directly account for wildcards). In JLS 8, 4.5.1 contains the assertion "The wildcard ? extends Object is equivalent to the unbounded wildcard ?" (see JDK-6480391). Now, for consistency with javac, it's proposed that "? extends B" be equivalent to "?", where B is the declaration-site bound. Or, more generally, if we can prove that two wildcards mean "the same thing" when taking into account declaration-site bounds, then they are equivalent. IMHO, this is a complex problem with minimal payoff; on the other hand, javac already implements it (some approximation, anyway), so it makes sense to consider encoding the existing behavior.
01-08-2014

Please look at the last comment.
24-08-2013

This issue relates to the definition of "same formal parameter type" in JDK-7023317, where it is clear that the JLS 8.4.2 rule is too strict. Unfortunately, the phrase "F1 contains F2 *and* F2 contains F1" is not very clear, as only type arguments can contain each other, not arbitrary types. Please add a complete description of how javac determines override-equivalence to this issue, and I will look at modifying the JLS to match.
24-08-2013

I think there's a question for you here. I probably forgot to reassign accordingly. See last comment.
15-04-2013

EVALUATION Javac (and other compilers) accept this program because override-equivalence is implemented in a different way w.r.t. JLS. More specifically, the algorithm in javac is more liberal than the one in the JLS: *) two formal argument types F1 and F2 are the same if either - F1 == F2 - F1 contains F2 *and* F2 contains F1 In this particular case, since the type-variable of Box is given a bound (Number) - the semantics of Box<?> is slightly changed, so that Box<?> is seen as contained by Box<? extends Number> [they are effectively the same thing].
03-03-2011

EVALUATION I believe javac is doing the right thing. Consider this: class Box<T> {} // Note no bound, unlike T in the Description class T6 { // fails static class A { void f(Box<?> box) {} } static class B extends A { void f(Box<? extends Number> box) {} } } javac is treating A.f and B.f as having different formal parameter types. (Each ? introduces a new type variable, and after renaming them as per 8.4.2, they have different bounds.) Thus they have different argument types, different signatures, aren't subsignatures of each other, and aren't override-equivalent. Further, B.f has the same erasure as A.f. By 8.4.8.3, a compile-time error occurs: name clash: f(Box<? extends java.lang.Number>) in T6.B and f(Box<?>) in T6.A have the same erasure, yet neither overrides the other
17-11-2006

EVALUATION This can't be right. "Same" should be a transitive property of method signatures. But I don't know how this property is specified. Recategorizing as a spec issue. When the spec issue is resolved, please recategorize as a compiler bug. ###@###.### 2003-11-13
13-11-2003