Field and array type resolution differs between reads and assignment targets

Open
#2,155 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
25/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Active
Tech stack
java
Domain
tooling

Research direction

Start in nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java and compare getAssignedVariableType with getTreeType, focusing on how each restores field annotations for identifiers, member selects, array accesses and assignment expressions. Read the review discussion in #2069 first, since it records the behavior change the author accepted. Done means reads and assignment targets share one field-type resolver without recursion, with regression tests covering inherited annotations and generic receivers, and raw types, captures and dataflow fallbacks still pass.

Written by the indexing model from the issue text.

Description

When checking reads and writes of generic fields and array elements, NullAway should resolve inherited nullness annotations and receiver substitutions consistently. The review of #2069 identified separate type-resolution paths that can disagree; consolidating them was deferred because it can change field-read behavior.

Follow-up to the review discussion in #2069. The author confirmed the behavior-change concern, and the reviewer requested a follow-up issue.

Context

In nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java, getAssignedVariableType overlaps with getTreeType in resolving identifiers, member selects, array accesses, and assignment expressions. The assignment-target path restores annotations from a field as a member of its receiver type, whereas getTreeType's member-select path restores annotations from the field's declared type.

This is a maintenance follow-up to #2069, rather than a newly reproduced release bug. The scope is the resolution difference identified in that review.

Proposed work

Share field and array location-type resolution between reads, assignment targets, and inference contexts. One possible approach is a common field-type resolver parameterized by calledFromDataflow, with ValueTarget adding the declaration contract around the resolved type. The implementation can choose a different structure.

Preserve raw-type handling, javac capture identity, and existing fallback behavior. Avoid introducing recursion between getTreeType and the assignment-target resolver. Treat changes to read behavior as deliberate semantic changes, with regression coverage, rather than assuming this is a mechanical extraction.

Acceptance criteria
  • Reads and assignment targets resolve a field as a member of its receiver type through shared logic, preserving inherited annotations and receiver substitutions.
  • Array-element and assignment-expression resolution reuse the applicable shared logic.
  • Regression tests cover the read/write resolution difference and pin down any changed diagnostics, including cases involving inherited annotations and generic receivers.
  • Raw types, wildcard captures, dataflow calls, and fallback paths retain their required behavior without recursive resolution.

Broader changes to generic inference are outside this follow-up.

Related issue

#1854 tracks a specific false negative when reading a generic field through a ? super receiver. This follow-up tracks consolidation of the resolution paths; any effect on that bug should be checked explicitly.

Duplicate searches across open and closed issues: repo:uber/NullAway is:issue "getAssignedVariableType", repo:uber/NullAway is:issue "getTreeType", and repo:uber/NullAway is:issue "2069". No existing consolidation issue was found.

Dominant language
Java
Stars
4.1k
Forks
379
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.