typetools / typetools/checker-framework
Optional#orElse(null)
@smillst is already working on this.
Since Feb 26, 2022.
- Dominant language
- Java
- Stars
- 1.1k
- Forks
- 440
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 134
Description
Hello,
I am in the process of annotating one of my projects for nullness checking and am currently trying to resolve all the issues CheckerFramework complains about. I am using the Gradle plugin (v 0.6.8) to invoke the CheckerFramework (v 3.21.2).
One piece of code I am having trouble to get CheckerFramework to accept is of the following pattern:
List<? extends @NonNull String> list = new ArrayList<>(Arrays.asList("bla", "blubb")); // From somewhere out of my control, can be empty, String is an example type for reproduction, the actual code uses various other types
Stream<? extends @NonNull String> stream = list.stream(); // In some cases I also only get the Stream, instead of the underlying Collection
Optional<? extends @NonNull String> optional = stream.findFirst();
@Nullable String string = optional.orElse(null);
The goal is for the string variable to either hold the first value of the stream, or null if the stream is empty. This code gives me the following output:
[argument] incompatible argument for parameter other of orElse.
@Nullable String string = optional.orElse(null);
^
found : @UnknownKeyFor NullType
required: capture#873[ extends @UnknownKeyFor String super @KeyForBottom Void]
I am having trouble to understand the issue here. Optional#orElse is marked as PolyNull in your annotated JDK, so I would have expected this to work. Is there a way to achieve what I want with Optional#orElse? A less elegant alternative might be for me to manually select a value based on Optional#isPresent.
I have also tried a few other variations of this code, all rejected by CheckerFramework by the same or different kinds of reasons.
List<? extends @NonNull String> list = new ArrayList<>(Arrays.asList("bla", "blubb")); // From somewhere out of my control, can be empty, String is an example type for reproduction, the actual code uses various other types
Stream<? extends @NonNull String> stream = list.stream();
Optional<? extends @NonNull String> optional = stream.findFirst();
@Nullable String string = optional.orElse((@Nullable String) null);
List<? extends @NonNull String> list = new ArrayList<>(Arrays.asList("bla", "blubb")); // From somewhere out of my control, can be empty, String is an example type for reproduction, the actual code uses various other types
Stream<? extends @NonNull String> stream = list.stream();
Optional<? extends @NonNull String> optional = stream.findFirst();
@Nullable String def = null;
@Nullable String string = optional.orElse(def);
List<? extends @NonNull String> list = new ArrayList<>(Arrays.asList("bla", "blubb")); // From somewhere out of my control, can be empty, String is an example type for reproduction, the actual code uses various other types
Stream<? extends @NonNull String> stream = list.stream();
Optional<? extends @NonNull String> optional = stream.findFirst();
@NonNull String def = "";
@Nullable String string = optional.orElse(def);
List<? extends @NonNull String> list = new ArrayList<>(Arrays.asList("bla", "blubb"));
Stream<? extends @NonNull String> stream = list.stream();
Optional<? extends @NonNull String> optional = stream.findFirst();
@NonNull String string = optional.orElse("");
The last one yields:
incompatible types: String cannot be converted to CAP#1
@NonNull String string = optional.orElse("");
^
where CAP#1 is a fresh type-variable:
CAP#1 extends @org.checkerframework.checker.nullness.qual.NonNull String from capture of ? extends @org.checkerframework.checker.nullness.qual.NonNull String
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.