Annotating lambda expressions

Remi Forax forax at univ-mlv.fr
Sat Jul 11 09:26:11 UTC 2015


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 
> <mailto: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 <http://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 <mailto: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/57eb713d/attachment-0001.html>


More information about the compiler-dev mailing list