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