JDK-7028808 : Incorrect ambiguity error for methods unified by generics
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P4
  • Status: Resolved
  • Resolution: Not an Issue
  • OS: generic
  • CPU: generic
  • Submitted: 2011-03-17
  • Updated: 2016-01-28
  • Resolved: 2013-09-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.
JDK 8
8Resolved
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
Example suggested by Sue:

public class GenericOverload {

interface Qoo<T> { void m(T arg); }
interface Roo<S extends Number> { void m(S arg); }
interface Ground extends Qoo<Integer>, Roo<Integer> {}
interface Param<T1, T2 extends Number> extends Qoo<T1>, Roo<T2> {}


void m(Ground g, Param<Integer, Integer> p, Integer i) {
  g.m(i); // ambiguity error (ok in ecj)
  p.m(i); // ambiguity error (also error in ecj)
}

}

The type Ground has members "Qoo<Integer>.m(Integer)" and "Roo<Integer>.m(Integer)".  The same is true for type Param<Integer,Integer>.

JLS 15.12.1 is clear that Ground and Param<Integer,Integer> are the types to search (it calls it "class or interface" frequently in this section, but it's clear from reading the details that this means "class or interface type," including the type arguments).

15.12.2.1 says that both methods should be identified as potentially applicable.  (In this and other sections, the only consistent interpretation of "method" is "the declared method, as instantiated by the type of which it is a member" -- the signature of the method is the signature after substitution.  For example, in 15.12.2.2, we have "Let m be a potentially-applicable method ... let S1..Sn be the types of the formal parameters of m" -- and S1..Sn must be the types after substitution.)

From 15.12.2.5, "It is possible that ... there are two or more methods that are maximally specific.  In this case: if all the maximally specific methods have override-equivalent signatures, then ... if all the maximally specific methods are declared abstract, and the signatures of all of the maximally specific methods have the same erasure, then the most specific method is chosen arbitrarily."

All of these conditions are met in both 'g.m(i)' and 'p.m(i)'.

Comments
Conclusion: javac's longstanding behavior is to interpret the erasure clause as the declaration-site signatures' erasures. Under that interpretation, this is not a bug. (It appears ecj's interpretation is to look at the erasure as a member of the bottom-most class, which is kind of weird.) Unless JDK-7028828 is resolved to clarify the interpretation of the clause differently, the status quo is fine.
12-09-2013

Please re-eval
13-08-2013

I don't fully agree with the evaluation; the spec says: "if all the maximally specific methods are declared abstract, and the signatures of all of the maximally specific methods have the same erasure, then the most specific method is chosen arbitrarily" Here, the two applicable methods don't have the same erasure (as type-parameter bounds differ). Several clarifications are needed in the spec: *) should erasure be computed on the instantiated method type as opposed to the declared method type (as this evaluation seems to suggest) ? *) should erasure mean erasure of arguments + return type, or just erasure of arguments? Javac currently compares erasures of declared argument types. Hence the ambiguity.
13-08-2013