JDK-8013224 : Most specific: spurious ambiguity error between abstract and default method
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8,8-repo-lambda
  • Priority: P2
  • Status: Resolved
  • Resolution: Not an Issue
  • Submitted: 2013-04-25
  • Updated: 2022-09-01
  • 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 :  
Description
There is a bug with most specific and default methods when two signatures are merged from a interface as a result of generic specialization:

class Test {
    public void testMergeAbstract(DA<String> da) {
        da.m("");
    }

    public void testMergeInterface(DI<String> di) {
        di.m("");
    }

    abstract class DA<T> {
      abstract int m(T arg);
      int m(String arg) { return 42; }
    }

    interface DI<T> {
      int m(T arg);
      default int m(String arg) { return 42; }
    }
}


This gives:

Test.java:234: error: reference to m is ambiguous
        di.m("");
          ^
  both method m(T) in DI and method m(String) in DI match
  where T is a type-variable:
    T extends Object declared in interface DI
1 error

Note that the dual case with abstract classes work just fine.
Comments
Resolution: this is not a bug. The treatment of DI is consistent with its treatment in javac 7 (where the default method is abstract). And under javac's reading of 15.12.2.5, this is consistent with the specification.
12-09-2013

Points: 1) The two cases are not equivalent. DA has a concrete method, which automatically gets priority ("If exactly one of the maximally specific methods is concrete..."). So DA doesn't help us figure out what DI should do. 2) If I try two abstract methods in either DA or DI, javac's longstanding behavior is to produce an ambiguity error. 3) It's not clear what "the signatures of all the maximally specific methods have the same erasure" means. If it's referring to the instantiated signatures, then this clause is trivially true (the methods are override-equivalent). But javac's interpretation is that it refers to declaration-site signatures.
12-09-2013

Turns out it's a broader issue with the new definition of most specific and how it deals with multiple abstract signatures: "Otherwise, if all the maximally specific methods are declared abstract, and the signatures of all the maximally specific methods have the same erasure (4.6), then the most specific method is chosen arbitrarily among the subset of the maximally specific methods that have the most specific return type." In the new spec draft, the part about erasure has been removed. This means the program above would be allowed as per this changes, but that's an incompatible change. If we fix javac to implement the spec draft the following regression test fails: http://hg.openjdk.java.net/jdk8/tl/langtools/file/tip/test/tools/javac/generics/Covar3.java Dan is currently investigating this.
08-05-2013