Use lambda parameter counts and block bodies for improved resolution #4796
Conversation
9fe9a79 to
5222d6b
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4796 +/- ##
===============================================
- Coverage 58.351% 58.326% -0.025%
- Complexity 2514 2518 +4
===============================================
Files 671 671
Lines 38782 38826 +44
Branches 7041 7054 +13
===============================================
+ Hits 22630 22646 +16
- Misses 13266 13295 +29
+ Partials 2886 2885 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 2 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
| parameterValue = ((EnclosedExpr) parameterValue).getInner(); | ||
| } | ||
| if (parameterValue.isLambdaExpr() || parameterValue.isMethodReferenceExpr()) { | ||
| if (parameterValue.isLambdaExpr()) { |
There was a problem hiding this comment.
Can you add comment here?
There was a problem hiding this comment.
Apologies for taking so long to get back to this. I've added a comment as requested explaining the reasoning behind adding this information to the LambdaArgumentTypePlaceholder. Please let me know if anything in the comment is unclear, or if I've missed something important
|
Very good work once again. Thanks again. |
…rgumentTypePlaceholder
This PR re-opens #4757 with a fix for the last crash I mentioned that occurred when attempting to find the functional method. Please see the bottom of the PR description for a description of the issue and fix.
Original PR description
This PR improves lambda-related method resolution by using the lambda parameter count and body for disambiguation in two cases described below. I implemented this by adding the required information to the
LambdaArgumentTypePlaceholderclass, but made sure that, if this information is not provided (such as forMethodReferenceExpr, type resolution behaviour will be the same as before this PR.Different parameter counts
Consumer.accepthas one parameter whileRunnable.runhas zero, so since the lambda has one parameter, we know this must resolve tofoo(Consumer<String>)Disambiguation by return type
In this example, the body of the lambda is a block statement which does not contain any return statements. This means that the lambda can only define a method with a
voidreturn type, so it must defineConsumer<String>(the same would be true forfoo(input -> { return; }).If it were
foo(input -> { return ""; })instead, then the reverse logic would apply. Since the return type of the lambda is notvoid, it cannot defineConsumerand must therefore defineFunction.New in this PR
This issue occurred when attempting to resolve a call to a method where one of the parameters is a functional interface that extends a different functional interface but overrides one of the generic types, for example:
In this example, the
Foo::foomethod reference has to be resolved to resolve theacceptsFunctioncall. 2 candidate methods for the method implemented byFoo::fooare found:and
At some point during the resolution, it must be determined whether these method return types are substitutable or not. The logic for doing this already exists, but
method1.isReturnTypeSubstitutable(method2.returnType())only handles the case where the return type of method2 is a type variable. If the return type of method1 is a type variable, then this crashes with anUnsupportedOperationException. I've added a fix where, if the return type of method1 is a type variable and all other checks have been done,falseis returned since in general the concrete return type ofmethod2cannot be substituted for the type variable.