val mis-infers an Optional<T> as Optional<Object> after map
See original GitHub issueShort description
IDEA, but not lombok itself, incorrectly identifies an Optional<Integer>
as Optional<Object>
when derived from an Optional<String>
via Optional::map
. It produces an inappropriate Quickfix to “fix” the change. Possible repeat of https://github.com/mplushnikov/lombok-intellij-plugin/issues/260 but doesn’t seem quite the same since it doesn’t involve conditionals.
Expected behavior
val strOpt = Optional.of("1");
val intOptInferredLambda = strOpt.map(str -> Integer.valueOf(str));
val intOptInferredMethodRef = strOpt.map(Integer::valueOf);
Optional<Integer> intOptExplicit = intOptInferredMethodRef; // works!
intOptExplicit = intOptInferredLambda; // Doesn't work, but it should. Err msg is: Required type: Optional. Provided: Optional
Version information
- IDEA Version: IntelliJ Ultimate 2019.3
- JDK Version: 1.8.0_51
- OS Type & Version: Mac 10.14.6
- Lombok Plugin Version: 0.29-2019.3
- Lombok Dependency Version: 1.18.12
Steps to reproduce
What steps do we need to take to reproduce this issue?
-
Ensure that you have the Bazel plugin and Lombok plugins installed
-
Open the sample project https://github.com/eboto/lombok-idea-val-bug
-
Observe that this is the code in the main method:
import lombok.val;
import java.util.Optional;
public class App {
public static void main(String... args) {
val strOpt = Optional.of("1");
val intOptInferredLambda = strOpt.map(str -> Integer.valueOf(str));
val intOptInferredMethodRef = strOpt.map(Integer::valueOf);
Optional<Integer> intOptExplicit = intOptInferredMethodRef;
intOptExplicit = intOptInferredLambda;
System.out.println("\n\nThe app built successfully and ran, showing that the compile error was only in idea, not in the code itself or lombok.\n");
}
}
- Observe the error on the
intOptExplicit = intOptInferredLambda
line. The error reads: Required type: Optional<Integer>. Provided: Optional<Object>
Sample project
https://github.com/eboto/lombok-idea-val-bug
- Sample project provided
- I am able to reproduce this error on the sample project by following the steps described above
Additional information
(Taken from my IDE in the sample project)
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (3 by maintainers)
Top Results From Across the Web
How to return value of optional after mapping in java 8
How can I return the string value? String previousReadyForHome = information.getPreviousContact().ifPresent(val->{ Arrays.stream(val.basic.
Read more >How to use map method in java.util.Optional - Tabnine
Determine a media type for the given resource, if possible. * @param resource the resource to introspect * @return the corresponding media type,...
Read more >Optional – map() and flatMap() operations
In this lesson, we will cover the map() and flatMap() methods from the Optional class in Java. public Optional map(Function.
Read more >Example usage for java.util Optional map - Java2s.com
If a value is present, returns an Optional describing (as if by #ofNullable ) the result of applying the given mapping function to...
Read more >Optional Class : filter, map and flatMap
Post-processing operations on Optional can be done using filter, map and flatMap. This methods are very useful once the method produces ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Ok I have provided a “fix” in #804 that makes the test-case work but can not yet explain how. I’ll leave it up to @mplushnikov to decide whether passing test-cases and that lame explanation work well enough for now.
That said, I want to capture my work up until this point. The first obvious question about the solution is: Why does a call to
LambdaUtil.getFunctionalInterfaceType
, either before or afterpsiExpression.getType()
result in fixing the bug? Meaning, why does it cause inferringstringOpt.map(str -> Integer.valueOf(str))
to correctly result in anOptional<Integer>
rather than in anOptional<Object>
?For bugs like this, the answer is always shared mutable state, and the only relevant shared mutable state I could find is
Map<PsiElement, PsiType> myMap
contained in ThreadLocalTypes.java, invoked bygetFunctionalInterfaceType
here. I have verified that, with the patch in #804, that cache ends up containing the correct value ofFunction1<String, Integer>
, but I have not verified that without the patch it does not.A rat’s nest of recursive calls to
ValProcessor.inferType
for this particular assignment has been confounding my analysis so rather then spend more cycles on this without further input, I figured I would supply this change that makes something better but doesn’t seem to make anything worse. After all, the tests pass 😉Hello @eboto, you can try new plugin release 0.32 with IntelliJ 2020.3 EAP Build together. It should contains the mentioned fix for your issue.