-
Notifications
You must be signed in to change notification settings - Fork 277
Java frontend: support lambda autoboxing involving generics #5363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java frontend: support lambda autoboxing involving generics #5363
Conversation
Turns out the usual lambda metafactory can apply boxing/unboxing, so you might see a situation like int myMethod(int i) { ... } interface MyLambdaType { Integer f(Integer i); } MyLambdaType mlt = SomeType::myMethod; And contrary to my prior expectations, the compiler doesn't generate a method stub to do the type conversion, it just directly requests an invokestatic lambda pointed at myMethod, regardless of the int vs. Integer clash. The lambda metafactory (which re-implement in JBMC) is then responsible for adding the necessary conversions.
This broadens our support for lambdas with implicit boxing/unboxing conversions to include those that use a method-reference to a method with type Object -> x to satisfy a functional interface of type primitive -> x (requiring boxing the parameter and then upcasting to Object), or a method with type x -> primitive satisfying an interface of type x -> Object (requiring the same conversion on the return value).
…type widening For example, an int -> int method is a valid instantiation of a functional interface that expects a byte -> int, or one that expects an int -> long. In both cases it's down to the metafactory / our code that emulates its behaviour to add the widening cast.
…d boxing/unboxing
…from a symbol-table id These users start with an irep_idt, so it's cheaper to look up by id than to create a derived string and then look up by that.
…to an interface method returning void
It's possible to use a primitive-typed method-reference to implement an appropriately specialised generic functional interface (e.g. something that takes an integer can satisfy Consumer<Byte> by direct method reference without needing to introduce a stub method to do the conversion). Here we implement that by unboxing using the java.lang.Number interface where necessary, thereby catching all valid widening numeric casts at the same time (Short.intValue for example will do the widening and deliver the required primitive type). When boxing we always box to the primitive type's corresponding boxed type, as this is all the compiler seems to allow (i.e. it won't allow satisfying Producer<Long> using a function that returns an int, even though that is type-safe). Note this solution uses virtual dispatch a little more often than is needed: in some simple cases the class file contains enough information to know that the Object we're unboxing must in practice be an Integer (for example) and so no dispatch is necessary. That doesn't account for all cases where a generic interface is implemented however, so I did not pursue this possibility.
Codecov Report
@@ Coverage Diff @@
## develop #5363 +/- ##
===========================================
+ Coverage 68.17% 68.19% +0.01%
===========================================
Files 1170 1171 +1
Lines 96540 96605 +65
===========================================
+ Hits 65819 65881 +62
- Misses 30721 30724 +3
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review of final commit only
lgtm - one question, but non-blocking
Based on #5359, extending that implementation to also account for generics