Annotating lambda expressions
Ron Pressler
ron at paralleluniverse.co
Sat Jul 11 12:59:09 UTC 2015
Thanks for the bootstrap argument tip! Will use that as a workaround.
Ron
On Sat, Jul 11, 2015 at 12:26 PM, Remi Forax <forax at univ-mlv.fr> wrote:
> On 07/11/2015 10:57 AM, Ron Pressler wrote:
>
> That's a very nice idea (in fact, we can do foo((@Special Runnable)
> ()->{...}), as well and get ASM to invoke a nice visitInsnAnnotation
> event), but it doesn't help, as I have no way of finding the method
> implementing the lambda by analyzing the bytecode.
>
>
> The method corresponding to the body of the lambda is one arguments of the
> bootstrap method of invokedynamic.
> see
> http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html
> (this translation scheme is not required to be used by compilers but in
> practice javac and ecj uses it and scalac will use it too)
>
> My suggestion says, "however the compiler chooses to represent the
> lambda, please apply the annotation to the implementing method, wherever it
> is". I think that the language spec at least implicitly forces the compiler
> to implement a lambda as a method *somewhere* (as opposed to, say, javac
> inlining the expression, as Kotlin does with inline functions).
>
>
> see above.
>
>
> The ability to attach introspectable metadata to a lambda expression
> that then travels with it to the implementing method -- wherever the
> compiler may choose to place it -- is extremely useful, and trumps, IMO,
> "purity" concerns re annotating expressions vs declarations, (esp. since
> we've already established that some expressions -- like cast and new -- are
> annotatable, and rightly so).
>
>
> cast and new are not annotatable, the type of a cast or a new are.
>
> Without this, we miss something important Java gives us, which is the
> ability to attach metadata to a method body. I fully understand the
> distinction that the annotation is applied to the *declaration* rather
> than the body itself, but that doesn't take away from the fact that a
> useful ability does not transfer to lambdas while it could be easily done.
>
> Ron
>
>
> Rémi
>
>
>
> On Sat, Jul 11, 2015 at 10:38 AM, Remi Forax <forax at univ-mlv.fr> wrote:
>
>> On 07/10/2015 11:41 PM, Ron Pressler wrote:
>>
>> I see no problem with cast annotations not being retrievable via
>> straightforward reflection just as I see no problem annotating the
>> generated method (which should always exist *somewhere*): in both cases,
>> those annotations are intended for use by tools that analyze the entire
>> project's source/bytecode (e.g. for typechecking/instrumentation) rather
>> than by specific reflective queries.
>>
>> What bothers me is that a capability that was trivial with inner
>> classes is now lost when using lambdas.
>>
>>
>> you can easily add a pattern recognizable by source/bytecode tools to do
>> what you want,
>> let suppose you have a static method like this:
>> static <T> T annotate(Class<? extends Annotation> annotation, T lambda)
>> { return lambda; }
>>
>> to annotate a lambda, your example can be written like this:
>> foo(annotate(Special.class, () -> { ...}))
>>
>> in the bytecode it will be translated to something like this:
>> ldc Special.class
>> invokedynamic ()Runnable
>> LambdaMetafactory + method handle ref on the lambda body
>> invokestatic Bar.annotate(Class, Object)Object
>> checkcast Runnable
>> invokevirtual Baz.foo(Runnable)...
>>
>> which is easy to recognize.
>>
>>
>> Ron Pressler
>> paralleluniverse.co
>> @puniverseco <https://twitter.com/puniverseco> on Twitter
>>
>>
>> Rémi
>>
>>
>>
>> On Fri, Jul 10, 2015 at 10:38 PM, Alex Buckley <
>> <alex.buckley at oracle.com>alex.buckley at oracle.com> wrote:
>>
>>> On 7/10/2015 2:31 AM, Maurizio Cimadamore wrote:
>>>
>>>> On 10/07/15 09:43, Ron Pressler wrote:
>>>>
>>>>> (Related to
>>>>>
>>>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009220.html
>>>>> )
>>>>>
>>>>> It is useful to add an annotation to a lambda expression -- as in
>>>>> foo(@Special () -> { ...}) -- which will be applied to the static
>>>>> method implementing the lambda (not to the interface the lambda
>>>>> implements). This would allow instrumentation tools operating on
>>>>> method implementations to handle lambdas. So far, AFAICT, this is not
>>>>> possible (or am I wrong?).
>>>>>
>>>> This is not possible, currently - as Remi said; you have annotations on
>>>> declarations (i.e. variable, classes, methods) - you have annotation on
>>>> types (i.e. type of a cast, type argument, etc.) - but you don't have
>>>> annotations on _expressions_.
>>>> I take it that, under the current translation scheme, there seems to be
>>>> a plausible description for what should happen when the lambda is
>>>> annotated; but what if the lambda is turned into a method reference (by
>>>> some IDE refactoring, or human intervention) ? In that case it is not
>>>> guaranteed that there would still be a physical place where to put the
>>>> annotation (unless we tell the compiler to 'expand' all annotated method
>>>> references).
>>>>
>>>
>>> Yes, the problem with annotations-on-expressions is not the language
>>> grammar but the storage of the annotations in the class file. With no
>>> standard way of translating source expressions to bytecode, there can be no
>>> standard API for retrieving annotations-on-expressions from bytecode. More
>>> broadly, there has never been a standard reflective API capable of
>>> inspecting method bodies.
>>>
>>> This explains why JSR 308 stayed away from annotations-on-expressions --
>>> we were not in a position to let them be read back. It was already bad
>>> enough that some annotations-on-types are stored in the class file at the
>>> level of individual bytecodes (e.g. an annotation on the type of a cast) so
>>> are not retrievable by any standard reflective API.
>>>
>>> Alex
>>>
>>
>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150711/e9875a60/attachment.html>
More information about the compiler-dev
mailing list