Annotating lambda expressions

Ron Pressler ron at paralleluniverse.co
Sat Jul 11 08:57:21 UTC 2015


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. 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).

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). 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

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>
> 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/1d85acae/attachment.html>


More information about the compiler-dev mailing list