Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7034913

15.12.2.5: Resolution of call to abstract methods is nondeterministic

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 5.0, 7, 8
    • Fix Version/s: 9
    • Component/s: specification
    • Labels:

      Description

      It is possible for more than one inherited abstract method of a class to have the same signature, and thus more than one method may be equally valid as the "most specific" choice for an invocation. In this situation, the following from JLS 3 15.12.2.5 applies:

      "Otherwise, if all the maximally specific methods are declared abstract, and the signatures of all of 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."

      (How to determine "the most specific return type" is unclear, but the assumption that it exists suggests that the intent must be to find the methods that are return-type-substitutable for all the candidates.)

      In the following example, both methods have "the most specific return type", and so both are equally valid, and the specified choice is arbitrary. This is unsatisfactory, because the nondeterministic choice can be observed.

      public class AbstractGeneric {

      interface A {
       <T> Iterable<T> foo();
      }

      interface B {
       Iterable foo();
      }

      abstract class C implements A, B {
       void test() {
         Iterable<String> l1 = ((A) this).foo(); // legal
         Iterable<String> l2 = ((B) this).foo(); // unchecked conversion
         Iterable<String> l3 = foo(); // unchecked conversion?
       }
      }

      }

      I think that the reasonable thing for 15.12.2.5 to say is that either only the erased one(s) or the erasures of all of them (as we do with SAM types) should be considered as candidates.

      To help get this right, here are some guarantees that we have from 8.4 on a maximal set of override-equivalent signatures in a class, assuming that they are all abstract:
      - One of the methods is return-type-substitutable for the others (its return type is either a subtype, a raw equivalent of a subtype, or the erased type variable upper bound of every other return type)
      - If there is a pair of return types R1 and R2 such that R1 = |R2| and R1 is "most specific", then R2 is also "most specific"
      - Every method has the same erased signature
      - If the method signatures are not "the same," then they can be divided into two groups of signatures that are, within the group, "the same." The first group is defined by the generic form of the signature, and the second group by the erased form.

      Given the definition of "most specific", however, I don't think that we can guarantee we're looking at the maximal set when we reach the end of 15.12.2.5. That is, it may be that some elements in the maximal set are strictly more specific than others (after type argument substitution). The first item above only applies to a maximal set, while the others apply equally to any subset.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                abuckley Alex Buckley
                Reporter:
                dlsmith Dan Smith
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: