Annotating lambda expressions

Ron Pressler ron at paralleluniverse.co
Sat Jul 11 13:02:59 UTC 2015


On Sat, Jul 11, 2015 at 3:59 PM, Ron Pressler <ron at paralleluniverse.co>
wrote:

> Thanks for the bootstrap argument tip! Will use that as a workaround.
>
>
... although it does require scanning the entire bytecode for the entire
project (to find the indy callsites) rather than just looking for annotated
methods...

R


>
> 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/35b2eb16/attachment-0001.html>


More information about the compiler-dev mailing list