Skip to content

Conversation

@msridhar
Copy link
Collaborator

@msridhar msridhar commented Sep 19, 2025

Previously, AtomicReference.get() was modeled as always returning @Nullable. Now, in JSpecify mode, we do not use that model. Instead, we model AtomicReference as a null-marked class with a nullable upper bound on its type variable. This required some tweaking to DefaultLibraryModels which now takes a Config object in its constructor and customizes its library models a bit based on that.

Fixes #681. This is an interim fix until we can address #950.

Summary by CodeRabbit

  • New Features

    • Nullability behavior for library methods is now config-driven, aligning with JSPECIFY mode settings.
    • Improved handling of AtomicReference: recognized as null-marked and with refined nullable-return logic based on configuration.
  • Bug Fixes

    • More accurate diagnostics for AtomicReference.get() depending on annotated type and JSPECIFY mode.
  • Tests

    • Added tests validating AtomicReference interactions under JSPECIFY mode, covering both nullable and non-null scenarios.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 19, 2025

Walkthrough

Makes LibraryModels config-driven by constructing DefaultLibraryModels with Config and computing nullable-returns per-config (JSPECIFY-aware). Updates sets (ALWAYS_NULLABLE_RETURNS split, added AtomicReference handling, NULLMARKED_CLASSES and NULLABLE_VARIABLE_TYPE_UPPER_BOUNDS). Adjusts loading path to pass Config. Adds a JSPECIFY-focused test validating AtomicReference.get() behavior.

Changes

Cohort / File(s) Summary
Config-driven LibraryModels
nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java
Construct DefaultLibraryModels(Config); rename NULLABLE_RETURNS to ALWAYS_NULLABLE_RETURNS; move AtomicReference.get() to new NULLABLE_RETURNS_JSPECIFY_MODE_DISABLED; add nullableReturnsForConfig built from config; nullableReturns() now returns per-config set; extend NULLMARKED_CLASSES with java.util.concurrent.atomic.AtomicReference; add upper-bound entry for AtomicReference index 0; update loader to pass config.
JSPECIFY tests for AtomicReference
nullaway/src/test/java/com/uber/nullaway/jspecify/JSpecifyLibraryModelsTests.java
New test class validating AtomicReference.get() nullability under OnlyNullMarked and JSPECIFY mode; asserts non-null for AtomicReference<Integer> and nullable-diagnostic for AtomicReference<@Nullable Integer>.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Analyzer
  participant Config
  participant LibraryModelsHandler
  participant DefaultLibraryModels as DefaultLibraryModels (per-config)

  Analyzer->>LibraryModelsHandler: loadLibraryModels(config)
  LibraryModelsHandler->>DefaultLibraryModels: new DefaultLibraryModels(config)
  activate DefaultLibraryModels
  note right of DefaultLibraryModels: Build nullableReturnsForConfig<br/>= ALWAYS_NULLABLE_RETURNS<br/>+ (if !config.isJSpecifyMode())<br/>  NULLABLE_RETURNS_JSPECIFY_MODE_DISABLED
  deactivate DefaultLibraryModels
  LibraryModelsHandler-->>Analyzer: LibraryModels

  Analyzer->>DefaultLibraryModels: nullableReturns()
  DefaultLibraryModels-->>Analyzer: nullableReturnsForConfig
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • lazaroclapp
  • yuxincs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately describes the primary change: updating how AtomicReference.get() is modeled when JSpecify mode is enabled and reflecting the config-driven library-model change; it names the API and the relevant mode and is concise enough for repository history.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue-681

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@msridhar msridhar requested review from Copilot, lazaroclapp and yuxincs and removed request for Copilot September 19, 2025 20:39
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
nullaway/src/test/java/com/uber/nullaway/jspecify/JSpecifyLibraryModelsTests.java (2)

10-30: JSPECIFY behavior well covered; consider adding a non-JSpecify counterpart.

This test correctly locks the JSPECIFY-mode semantics for AtomicReference.get(). Please add a companion test with JSpecifyMode=false to guard the legacy behavior (get() treated as @nullable), preventing regressions across modes.


32-36: Add -XDaddTypeAnnotationsToSymbol=true to stabilize type-use handling across JDKs.

Keeps type annotations available on symbols during compilation, reducing flakiness across compiler versions.

   private CompilationTestHelper makeHelper() {
     return makeTestHelperWithArgs(
         Arrays.asList(
-            "-XepOpt:NullAway:OnlyNullMarked=true", "-XepOpt:NullAway:JSpecifyMode=true"));
+            "-XepOpt:NullAway:OnlyNullMarked=true",
+            "-XepOpt:NullAway:JSpecifyMode=true",
+            "-XDaddTypeAnnotationsToSymbol=true"));
   }
nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java (2)

842-844: Correct gating of AtomicReference.get() for non-JSpecify mode.

The separate NULLABLE_RETURNS_JSPECIFY_MODE_DISABLED keeps legacy behavior intact when JSPECIFY is off.

Optional: rename to NULLABLE_RETURNS_WHEN_JSPECIFY_DISABLED for readability.


901-905: AtomicReference added to null-marked classes; confirm no effect when JSPECIFY is off.

If the NullMarkedClasses hook is consulted outside JSPECIFY mode, this could subtly change legacy semantics. If that’s possible, consider gating this via config as you did for nullableReturns.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 036d593 and 371c46b.

📒 Files selected for processing (2)
  • nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java (5 hunks)
  • nullaway/src/test/java/com/uber/nullaway/jspecify/JSpecifyLibraryModelsTests.java (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-14T18:50:06.159Z
Learnt from: msridhar
PR: uber/NullAway#1245
File: guava-recent-unit-tests/src/test/java/com/uber/nullaway/guava/NullAwayGuavaParametricNullnessTests.java:101-102
Timestamp: 2025-08-14T18:50:06.159Z
Learning: In NullAway JSpecify tests, when JDK version requirements exist due to bytecode annotation reading capabilities, prefer failing tests over skipping them on unsupported versions to ensure CI catches regressions and enforces proper JDK version usage for developers.

Applied to files:

  • nullaway/src/test/java/com/uber/nullaway/jspecify/JSpecifyLibraryModelsTests.java
🧬 Code graph analysis (1)
nullaway/src/test/java/com/uber/nullaway/jspecify/JSpecifyLibraryModelsTests.java (1)
nullaway/src/test/java/com/uber/nullaway/NullAwayTestsBase.java (1)
  • NullAwayTestsBase (9-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build and test on ubuntu-latest
  • GitHub Check: Build caffeine with snapshot
  • GitHub Check: Build and test on windows-latest
  • GitHub Check: Build and test on macos-latest
  • GitHub Check: Build spring-framework with snapshot
🔇 Additional comments (5)
nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java (5)

389-389: Plumbing Config into DefaultLibraryModels is correct.

This enables per-config model shaping without affecting external models ordering.


818-840: Good: AtomicReference.get() removed from always-nullable set.

Matches the new JSPECIFY modeling where nullability depends on the type argument.


897-898: Add nullable upper bound for AtomicReference (index 0).

This is the key to JSPECIFY semantics; looks right.

Please confirm no additional Atomic* types (e.g., AtomicReferenceArray) also need upper-bound modeling for parity.


909-922: Per-config nullableReturns cache is clean and efficient.

One-time computation via constructor keeps lookups fast and logic clear.


954-956: Switched to config-derived nullable returns.

Return path now reflects the chosen mode; LGTM.

@codecov
Copy link

codecov bot commented Sep 19, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.49%. Comparing base (a389f54) to head (c2c38be).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1298      +/-   ##
============================================
+ Coverage     88.47%   88.49%   +0.01%     
  Complexity     2476     2476              
============================================
  Files            93       93              
  Lines          8203     8214      +11     
  Branches       1616     1617       +1     
============================================
+ Hits           7258     7269      +11     
  Misses          474      474              
  Partials        471      471              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@msridhar
Copy link
Collaborator Author

Looks like this breaks the build for both Caffeine and Spring :-) I'll see if I can do upstream PRs on those projects before landing this one (assuming the fixes don't cause new errors with the current NullAway release...)

Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@msridhar
Copy link
Collaborator Author

I opened a PR for the Spring failures and I'm pretty confident in it, so I'm going to go ahead and land this.

@msridhar msridhar merged commit d0abadd into master Sep 20, 2025
13 of 16 checks passed
@msridhar msridhar deleted the issue-681 branch September 20, 2025 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Respect annotated AtomicReference's

3 participants