question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

val mis-infers an Optional<T> as Optional<Object> after map

See original GitHub issue

Short 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?

  1. Ensure that you have the Bazel plugin and Lombok plugins installed

  2. Open the sample project https://github.com/eboto/lombok-idea-val-bug

  3. 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");
  }
}
  1. 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) lombok_idea_bug

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
ebotocommented, May 25, 2020

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 after psiExpression.getType() result in fixing the bug? Meaning, why does it cause inferring stringOpt.map(str -> Integer.valueOf(str)) to correctly result in an Optional<Integer> rather than in an Optional<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 by getFunctionalInterfaceType here. I have verified that, with the patch in #804, that cache ends up containing the correct value of Function1<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 😉

0reactions
mplushnikovcommented, Sep 25, 2020

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.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found