<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Brian,<div class=""><br class=""></div><div class="">Request from the VM - it would make implementations seriously easier to make consistent if we can ensure that the JVMS does not</div><div class="">contain the term “arbitrary”. So yes, please, I would recommend that the static compiler filter out such situations of duplicate equally</div><div class="">applicable members and it would be an error if there were no clear more specific candidate member.</div><div class=""><br class=""></div><div class="">thanks,</div><div class="">Karen</div><div class=""><br class=""></div><div class=""><div><blockquote type="cite" class=""><div class="">On Mar 29, 2016, at 3:52 PM, Brian Goetz <<a href="mailto:brian.goetz@oracle.com" class="">brian.goetz@oracle.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
  

    <meta http-equiv="content-type" content="text/html; charset=utf-8" class="">
  
  <div bgcolor="#FFFFFF" text="#000000" class="">
    <tt class="">Yet another in a series of disconnected, bottom-up (starting at
      the VM) memos laying the groundwork for the enhanced generics
      model.  <br class="">
      <br class="">
      Basic Problem<br class="">
      =============<br class="">
      <br class="">
      It may be desirable, for purposes of expressiveness or migration
      compatibility, to declare class members that are only members of a
      specific subset of parameterizations of a generic class.  Examples
      include:<br class="">
      <br class="">
       - Reference-specific API assumptions.  In our analysis of the
      Collection classes, we identified various methods that fail to
      make the jump to any-generics for various reasons.  These include
      methods like Collection.toArray(), whose signature makes no sense
      for primitive parameterizations, or Map.get(), which uses `null`
      (not in the domain of primitives) to indicate "not present."  We
      can't take these methods away from reference instantiations, but
      we don't want to propagate them into primitive instantiations.  <br class="">
      <br class="">
       - Better implementations enabled by known type parameters. 
      Generic classes will provide generic implementations, but
      sometimes better implementations are possible when concrete types
      are known.  In this case, an implementation would provide a
      generic implementation and zero or more implementations that are
      restricted to more specific implementations.  <br class="">
      <br class="">
       - Functionality available only on specific implementations.  For
      example, List<int> could have a sum() method even though
      sum() does not make sense on all instantiations.  (This is the
      declaration-site version of what C# enables at the use site with
      extension methods -- allowing methods to be injected into types,
      rather than classes.)  <br class="">
      <br class="">
      <br class="">
      We've not yet spent a lot of time identifying the proper way to
      surface this in the language.  For methods, one possibility is to
      use receiver parameters (added in Java SE 8) to qualify the
      receiver type:<br class="">
      <br class="">
          int sum(List<int> this) { ... }<br class="">
      <br class="">
      This gets the point across clearly enough (and is analogous to how
      C# does extension methods), but has several drawbacks: doesn't
      scale to fields, nor does it scale well to a
      conditional-membership model that is anything other than "I am a
      member of parameterization X".  (Where this might fall down, for
      example, would be when we want members declared as "I am *not* a
      member of parameterization X".)  <br class="">
      <br class="">
      Note that in the second motivating example, there will be two
      members signatures with the same name and signature; we want one
      to take precedence over the other.  <br class="">
    </tt><br class="">
    <tt class=""><tt class="">We call these "conditional" or "restricted" members.<br class="">
        <br class="">
      </tt><br class="">
      Classfile Strawman<br class="">
      ==================<br class="">
      <br class="">
      Here's a strawman of how we might represent this at the VM level. 
      <br class="">
      <br class="">
      We define a new attribute, `Where`, which can be applied to
      instance fields, instance methods, and constructors:<br class="">
    </tt><tt class=""><br class="">
    </tt><code class="">    Where { <br class="">
              u2 name_index; <br class="">
              u4 length; <br class="">
              u2 restrictionDomain;</code><tt class=""> // refers to a ParamType
      constant<br class="">
          }<br class="">
      <br class="">
      The restriction domain indicates the parameterization to which
      this member is restricted; in the absence of Where attribute, it
      is assumed to be ThisClass<any, any, ...>.  <br class="">
    </tt><tt class=""><br class="">
      When loading a parameterization of a generic class, we perform an
      applicability check for each member as we encounter it; in the
      model outlined here, this is a straight subtyping check of the
      current parameterization against the restriction domain.  <br class="">
      <br class="">
      It is possible there could be duplicate applicable methods; this
      arises when we have a specialization-specific "override", as in:<br class="">
      <br class="">
      class Foo<any T> {<br class="">
          // total method m(T)<br class="">
          void m(T t) { }<br class="">
      <br class="">
          // Specialization of m(T) for T=int<br class="">
          void m(Foo<int> this, int i) { ... }<br class="">
      }<br class="">
      <br class="">
      When we find a duplicate applicable member, we perform a "more
      specific" check comparing the restriction domains; in this case,
      the second method has a restriction domain of Foo<int>,
      which is more specific than the (implicit) Foo<any>
      restriction domain of the generic method, so we prefer the second
      member.  <br class="">
    </tt><tt class=""><tt class=""><br class="">
      </tt> This procedure is strictly linear; as each member is read
      from the classfile, we can make a quick determination as to
      whether to keep or discard it; if we keep it, we might replace it
      later with a more specific one as we find it.  Modulo cases where
      there are multiple applicable overloads that are equally specific,
      it is also deterministic; whether we find the generic version of
      m() or its specialization first, we'll end up with the same set of
      members. <br class="">
      <br class="">
    </tt><tt class=""><tt class="">If there are duplicate applicable members in a
        classfile where neither's restriction domain is more specific
        than the other's, then the VM is permitted to make an arbitrary
        choice (as they are both applicable and equally specific.)  The
        static compiler can work to filter out such situations, if
        desired, such as imposing a "meet rule"; if we had:<br class="">
        <br class="">
            void foo(Foo<int,any> this)<br class="">
            void foo(Foo<any,int> this)<br class="">
        <br class="">
        a meet rule would require the additional overload<br class="">
      </tt><br class="">
      <tt class=""><tt class="">    void foo(Foo<int,int> this)<br class="">
        </tt></tt><br class="">
      <br class="">
      <br class="">
    </tt>
  </div>

</div></blockquote></div><br class=""></div></body></html>