typetools / typetools/checker-framework
Optional checker: possible erroneous report of an incompatible method receiver for `Optional#get` in a `Stream#map`
@smillst is already working on this.
Since Sep 29, 2023.
- Dominant language
- Java
- Stars
- 1.1k
- Forks
- 440
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 134
Description
Summary
Running the Optional checker on code that contains a call to Optional#get within a call to .map on a Java stream produces an error reporting to an incompatible method receiver.
Commands executed
Using the latest commit on the master branch of the Checker Framework, where javacheck is an alias for javac included in the Checker Framework's binary distribution.
javacheck -processor optional Main.java
Input
This is a minimal test case that should be able to trigger this issue
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class Main {
public List<Integer> getOnlyPresentInts(List<Optional<Integer>> optInts) {
return optInts.stream()
.map(Optional::get)
.collect(Collectors.toList());
}
}
Actual output
Main.java:9: warning: [optional.as.element.type] Don't use Optional as the element type in a collection.
public List<Integer> getOnlyPresentInts(List<Optional<Integer>> optInts) {
^
Main.java:11: error: [methodref.receiver] Incompatible receiver type
.map(Optional::get)
^
found : @Present Optional<@MaybePresent Integer>
required: @MaybePresent Optional<@MaybePresent Integer>
Consequence: method in @MaybePresent Optional<@MaybePresent Integer>
@MaybePresent Integer get(@Present Optional<@MaybePresent Integer> this)
is not a valid method reference for method in @MaybePresent Function<@MaybePresent Optional<@MaybePresent Integer>, @MaybePresent Integer>
@MaybePresent Integer apply(@MaybePresent Function<@MaybePresent Optional<@MaybePresent Integer>, @MaybePresent Integer> this, @MaybePresent Optional<@MaybePresent Integer> p0)
1 error
1 warning
Expected output
There should technically be no error about an incompatible method receiver, as calling .stream() on an object of type List<Optional<Integer>> should evaluate to an object of type Stream<Optional<Integer>>.
Additionally, the error line
Main.java:11: error: [methodref.receiver] Incompatible receiver type
.map(Optional::get)
^
found : @Present Optional<@MaybePresent Integer>
required: @MaybePresent Optional<@MaybePresent Integer>
Is confusing to me, shouldn't the found type be annotated with @MaybePresent? Since the manual states
@MaybePresent
The annotated Optional container may or may not contain a value. This is the default type, so programmers do not have to
write it.
However, this might be a misunderstanding of the Optional checker's type system on my part.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.