Annotating lambda expressions

Remi Forax forax at univ-mlv.fr
Sat Jul 11 13:39:37 UTC 2015


On 07/11/2015 03:02 PM, Ron Pressler wrote:
>
> On Sat, Jul 11, 2015 at 3:59 PM, Ron Pressler <ron at paralleluniverse.co 
> <mailto: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...

??
finding annotated methods requires to scan the entire project too ?

>
> R

R

>
>     On Sat, Jul 11, 2015 at 12:26 PM, Remi Forax <forax at univ-mlv.fr
>     <mailto: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
>         <http://cr.openjdk.java.net/%7Ebriangoetz/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/ab710809/attachment-0001.html>


More information about the compiler-dev mailing list