JSpecify JDK models: `list.toArray()` on a `List<String>` is reported as `@Nullable Object []` where `Object[]` is expected

Open
#1,988 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
46/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
java
Domain
backend, devtools

Research direction

Start in nullaway/src/test/java/com/uber/nullaway/jspecify/ and reproduce the reported assignment with the JSpecify test helper and flags from the issue. Then read the PolyNull library model work in #1813 and its receiver-location handling; the issue says receiver locations are currently rejected. Done means the non-null List<String> case passes without a diagnostic while the nullable-element case remains nullable, including the broader toArray() declarations mentioned in the typetools JDK.

Written by the indexing model from the issue text.

Description

enhancement jdk-models jspecify

With JSpecify JDK models on, toArray() on a List<String> returns @Nullable Object[], so storing the result in an Object[] is reported as incompatible types: @Nullable Object [] cannot be converted to Object [], although no element of a List<String> is null.

Versions: NullAway master at a03b7bb90 (0.14.3-SNAPSHOT) and the head of #1813 (5f01b5728); both report the same. Error Prone 2.50.0, JDK 21.0.9. Flags: -XepOpt:NullAway:JSpecifyMode=true -XDaddTypeAnnotationsToSymbol=true -XepOpt:NullAway:JSpecifyExperimental=true -XepOpt:NullAway:OnlyNullMarked=true; JSpecifyExperimental turns on JSpecifyJDKModels.

Code sample. I ran it as a test in nullaway/src/test/java/com/uber/nullaway/jspecify/, with makeTestHelperWithArgs(JSpecifyJavacConfig.withJSpecifyModeArgs(List.of("-XepOpt:NullAway:OnlyNullMarked=true"))).

import java.util.List;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
class Test {
  Object[] nonNullElements(List<String> list) {
    Object[] array = list.toArray();
    return array;
  }
  @Nullable Object[] nullableElements(List<@Nullable String> list) {
    @Nullable Object[] array = list.toArray();
    return array;
  }
}

Expected: no diagnostic on line 7. Collection.toArray() returns "an array containing all of the elements in this collection", and the elements of a List<String> exclude null, so the array component is @NonNull here. For the List<@Nullable String> on line 11 it stays @Nullable, which is what the JDK model says today.

Actual: the test fails on master and on the #1813 head with:

java.lang.AssertionError: Saw unexpected error on line 7. All errors:
/Test.java:7: warning: [NullAway] incompatible types: @Nullable Object [] cannot be converted to Object []
    Object[] array = list.toArray();
             ^
    (see http://t.uber.com/nullaway )

Context. #1728 reported this call-site error together with an override error for toArray(); #1722 fixed the override half, and this half remains. The nullness of the result follows the receiver's element type, which is what the typetools JDK writes as @PolyNull Object[] toArray(List<@PolyNull E> this). #1813 adds PolyNull library models, but a location on the receiver (PolyNullLocation.Receiver) is rejected with PolyNull receiver locations are not yet supported for ..., so this model cannot be written yet. Receiver support was left for a follow-up in https://github.com/uber/NullAway/pull/1813#issuecomment-5836616054 and https://github.com/uber/NullAway/pull/1813#issuecomment-6227027927; this issue tracks it. In the typetools JDK the same toArray() pattern appears in more than 30 declarations across java.util, java.util.concurrent, and Stream.

Dominant language
Java
Stars
4.1k
Forks
381
Avg merge
1d 2h
Merged PRs (30d)
106

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from uber/NullAway

All issues in uber/NullAway

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.