Deconstructor reflection Was: Re: Deconstruction patterns

Brian Goetz brian.goetz at oracle.com
Wed Mar 8 17:18:40 UTC 2023


That's sort of where I was coming from.  For example, when we added 
Class::getRecordComponents (which, btw, should really be a pattern), it 
returns RecordComponent[] instead of List<RecordComponent>, because 
that's how reflection rolls.  The benefit of using List (which are 
clearly "better" than arrays) is lost by the inconsistency of "some 
methods return arrays, some return lists."

On 3/8/2023 12:05 PM, Dan Heidinga wrote:
> Thanks for the response.  This seems reasonable though I still have an 
> aversion to the Object[] return type for the `match` method though it 
> fits with the way reflection works today.  I hate wasting the Carrier 
> runtime's benefits by immediately boxing and collecting to the array 
> for reflection but maybe anything else is trying to fix the sins of 
> the past?
>
> --Dan
>
> On Tue, Mar 7, 2023 at 3:16 PM Brian Goetz <brian.goetz at oracle.com> wrote:
>
>
>
>     On 3/7/2023 2:51 PM, Dan Heidinga wrote:
>>
>>
>>         #### Reflection
>>
>>         Since matchers are a new kind of class member, they will need
>>         a new kind of
>>         reflective object, and a method that is analogous to
>>         `Class::getConstructors`.
>>         The reflective object should extend `Executable`, as all of
>>         the existing
>>         methods
>>         on `Executable` make sense for patterns (using `Object` as
>>         the return
>>         type.)  If
>>         the pattern is reflectively invoked, it returns `null` for no
>>         match, or an
>>         `Object[]` which is the boxing of the values in the carrier.
>>
>>
>>     This surprised me slightly and I'm not sure I follow the
>>     reasoning on why the return value would be boxed and collected
>>     into an Object[]?
>>
>>     The design says matcher methods return Object as an opaque
>>     descriptor for the actual implementation carrier object.  Yet,
>>     reflection will take that carrier object, and replace it with an
>>     equivalent Object[] resulting in more allocations and
>>     (potentially) boxing on the return path.
>>
>>     I get it's a developer friendly approach but I wonder if it
>>     encourages the wrong mental model about what matchers return?
>>
>>     Would it make sense to add an extra step in that process so the
>>     java.lang.reflect.Matcher instance has a `Object[]
>>     resultToArray(Object)` method?  It's more ceremony (yuck) but
>>     allows avoiding the array creation and maybe the boxing on the
>>     return path for allocation-sensitive callers?
>
>     There's a few things here, let's try to unpack them.
>
>     I agree that the actual classfile descriptor of the synthetic
>     method need not be all that related to what reflection does,
>     though it is nice to minimize that difference if we can.
>
>     Reflection routinely boxes everything; if you're working
>     reflectively, this is just the price of entry? MethodHandles are a
>     different story, of course, and we should be able to unreflect a
>     Matcher to something that can be invoked directly.
>
>     I had been assuming that `invoke` was a method on Executable, but
>     now that I look, I realize that invocation lives on the subclasses
>     Method and Constructor.  So we have more latitude than I thought. 
>     Which nudges me a little towards
>
>         Object[] match(Object matchTarget, Object... additionalArgs)
>
>     where match failure is reflected as null.
>
>     This also nudges me a bit towards hiding matchers from
>     getMethods() and friends (as we do with constructors).
>
>>     And speaking of MethodHandles, will there be new
>>     MethodHandles.Lookup.findMatcher , findDeconstructor, etc
>>     methods?  Or do you see them being looked up with the existing
>>     find* methods?
>
>     I had been assuming that we would use MethodHandle::findStatic for
>     this.
>
>>         We will then need some additional methods to describe the
>>         bindings, so the
>>         subtype of `Executable` has methods like `getBindings`,
>>         `getAnnotatedBindings`,
>>         `getGenericBindings`, `isDeconstructor`, `isPartial`, etc. 
>>         These
>>         methods will
>>         decode the `Matcher` attribute and its embedded attributes.
>>
>>
>>     What does `getBindings` return?  The MethodType describing the
>>     bindings?  A Class[] describing the types of the bindings? 
>>     Something else?
>>
>
>         Class[] getBindings();
>         Type[] getGenericBindings();
>         AnnotatedType[] getAnnotatedBindings();
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20230308/9882b2bd/attachment-0001.htm>


More information about the amber-spec-experts mailing list