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