Skip to content

@SideEffectFree annotations - #282

Open
mernst wants to merge 16 commits into
typetools:masterfrom
mernst:side-effects-only-2
Open

@SideEffectFree annotations#282
mernst wants to merge 16 commits into
typetools:masterfrom
mernst:side-effects-only-2

Conversation

@mernst

@mernst mernst commented Jul 14, 2026

Copy link
Copy Markdown
Member

Merge with typetools/checker-framework#7818 .

Co-Authored-By: James Yoo <jyoo980@gmail.com>
Co-Authored-By: Rashmi Mudduluru <rashmi4@cs.washington.edu>

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d60a2120-5fd1-4670-a0e9-dd96dbd05e22

📥 Commits

Reviewing files that changed from the base of the PR and between d4a2682 and 192472e.

📒 Files selected for processing (2)
  • src/java.base/share/classes/java/util/IdentityHashMap.java
  • src/java.base/share/classes/java/util/LinkedHashSet.java

📝 Walkthrough

Walkthrough

The PR activates Checker Framework @SideEffectsOnly annotations across Java base APIs and implementations. It adds @SideEffectFree annotations to reversal and iterator methods. It updates annotation metadata, formatter behavior, Javadocs, and README link punctuation. Runtime algorithms and method bodies remain generally unchanged.

Possibly related PRs

  • typetools/jdk#265 — Overlaps on String.getChars and related side-effect annotations.
  • typetools/jdk#275 — Modifies many of the same SideEffectsOnly annotation sites.
  • typetools/jdk#276 — Overlaps on Checker Framework receiver and effect annotations.
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
src/java.base/share/classes/sun/net/www/HeaderParser.java (1)

212-216: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Enforce the Iterator contract by throwing NoSuchElementException.

While the annotation additions are correct, the next() method itself violates the standard Iterator contract. If called when the iterator is exhausted, it throws an unexpected ArrayIndexOutOfBoundsException instead of a NoSuchElementException.

Add a boundary check to throw the correct exception.

🐛 Proposed fix
         `@SideEffectsOnly`("this")
         `@DoesNotUnrefineReceiver`("modifiability")
         public String next () {
+            if (!hasNext()) {
+                throw new java.util.NoSuchElementException();
+            }
             return tab[index++][returnsValue?1:0];
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/sun/net/www/HeaderParser.java` around lines 212 -
216, Update HeaderParser.next() to check whether the iterator is exhausted
before indexing tab, and throw NoSuchElementException when index has reached the
available entries. Preserve the existing return and index-advance behavior for
valid elements.
src/java.base/share/classes/java/util/regex/Matcher.java (1)

1359-1369: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include the enclosing instance in these @SideEffectsOnly lists.
"this" only covers the iterator object; these methods also mutate the outer collection.

  • src/java.base/share/classes/java/util/regex/Matcher.java#L1359-L1369: add Matcher.this
  • src/java.base/share/classes/java/util/RegularEnumSet.java#L138-L145: add RegularEnumSet.this
  • src/java.base/share/classes/java/util/PriorityQueue.java#L572-L594: add PriorityQueue.this
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/regex/Matcher.java` around lines 1359 -
1369, Update the `@SideEffectsOnly` annotations on the affected iterator methods
to include both the iterator receiver and its enclosing collection instance: add
Matcher.this in
src/java.base/share/classes/java/util/regex/Matcher.java:1359-1369,
RegularEnumSet.this in
src/java.base/share/classes/java/util/RegularEnumSet.java:138-145, and
PriorityQueue.this in
src/java.base/share/classes/java/util/PriorityQueue.java:572-594.
src/java.base/share/classes/java/util/concurrent/BlockingQueue.java (1)

380-409: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include c in drainTo’s side-effect spec. Both overloads can mutate c as well as this, so @SideEffectsOnly("this") is incomplete; list both targets with the argument-expression form (for example, @SideEffectsOnly({"this", "#1"})).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/concurrent/BlockingQueue.java` around
lines 380 - 409, Update both drainTo overloads in BlockingQueue so their
`@SideEffectsOnly` annotations include both the receiver and collection argument
c, using the argument-expression target form "`#1`". Leave the existing
`@DoesNotUnrefineReceiver` annotations and method signatures unchanged.
src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java (1)

1125-1138: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Include the collection parameter in the @SideEffectsOnly annotation.

The drainTo methods mutate the provided collection c by adding elements to it (c.add(e)). Therefore, the @SideEffectsOnly("this") annotation is incorrect as it claims only the receiver (this) is modified.

Consider updating the annotation to include the first parameter, for example, @SideEffectsOnly({"this", "#1"}), so that the static analysis correctly tracks the mutation on the passed collection.

🐛 Proposed fix
-    `@SideEffectsOnly`("this")
+    `@SideEffectsOnly`({"this", "`#1`"})
     `@DoesNotUnrefineReceiver`("modifiability")
     public int drainTo(`@GuardSatisfied` `@CanShrink` SynchronousQueue<E> this, Collection<? super E> c) {

And similarly for the other drainTo overload:

-    `@SideEffectsOnly`("this")
+    `@SideEffectsOnly`({"this", "`#1`"})
     `@DoesNotUnrefineReceiver`("modifiability")
     public int drainTo(`@GuardSatisfied` `@CanShrink` SynchronousQueue<E> this, Collection<? super E> c, int maxElements) {

Also applies to: 1143-1156

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java`
around lines 1125 - 1138, Update the `@SideEffectsOnly` annotations on both
drainTo overloads in SynchronousQueue to include the collection parameter
alongside "this" (for example, "this" and "`#1`"), so the mutation performed by
c.add(e) is correctly tracked.
src/java.base/share/classes/java/util/Collections.java (1)

1204-1215: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Remove incorrect @SideEffectsOnly from read-only methods. Read-only view methods and stream-creation methods were erroneously annotated with @SideEffectsOnly("this") and @DoesNotUnrefineReceiver("modifiability"). This incorrectly flags them as mutators and breaks static analysis by preventing their use on immutable references. The shared root cause is likely a copy-paste error during the mass annotation update.

  • src/java.base/share/classes/java/util/Collections.java#L1204-L1215: remove the mutator annotations from stream() and parallelStream().
  • src/java.base/share/classes/java/util/Collections.java#L1271-L1275: remove the mutator annotations from reversed().
  • src/java.base/share/classes/java/util/Collections.java#L1401-L1405: remove the mutator annotations from reversed().
  • src/java.base/share/classes/java/util/Collections.java#L1450-L1464: remove the mutator annotations from subSet, headSet, and tailSet.
  • src/java.base/share/classes/java/util/Collections.java#L1550-L1577: remove the mutator annotations from descendingSet, subSet, headSet, and tailSet.
  • src/java.base/share/classes/java/util/Collections.java#L1671-L1673: remove the mutator annotations from listIterator(int).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/Collections.java` around lines 1204 -
1215, Remove `@SideEffectsOnly`("this") and
`@DoesNotUnrefineReceiver`("modifiability") from the read-only methods in
Collections.java: stream() and parallelStream() at lines 1204-1215, reversed()
at 1271-1275 and 1401-1405, subSet(), headSet(), and tailSet() at 1450-1464,
descendingSet(), subSet(), headSet(), and tailSet() at 1550-1577, and
listIterator(int) at 1671-1673. Leave their existing implementations and other
annotations unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/java.base/share/classes/java/lang/StringBuilder.java`:
- Around line 502-505: Remove the contradictory `@SideEffectFree` annotation from
StringBuilder.repeat(int codePoint, int count), keeping `@SideEffectsOnly`("this")
and the existing method behavior unchanged.

In `@src/java.base/share/classes/java/util/concurrent/DelayQueue.java`:
- Around line 406-408: Update the `@SideEffectsOnly` annotations on both drainTo
overloads in src/java.base/share/classes/java/util/concurrent/DelayQueue.java at
lines 406-408 and 418-420, and both drainTo overloads in
src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java at
lines 751-753 and 763-765, to declare mutations of both the receiver and the
first parameter using {"this", "`#1`"}.

In `@src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java`:
- Around line 728-730: Update both LinkedBlockingQueue.drainTo overloads at
src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java lines
728-730 and 740-742: expand `@SideEffectsOnly` to include both "this" and the
first parameter ("`#1`" or "c"), preserving the existing `@DoesNotUnrefineReceiver`
annotation.

In `@src/java.base/share/classes/java/util/Deque.java`:
- Line 385: Remove the incorrect `@SideEffectsOnly`("this") annotations from the
read-only methods at src/java.base/share/classes/java/util/Deque.java lines 385,
396, 537, 552, 692, and 706; use `@SideEffectFree` instead at lines 692 and 706
where appropriate. Remove the annotation from
src/java.base/share/classes/java/util/SequencedSet.java line 60 and consider
`@SideEffectFree`, and remove it from
src/java.base/share/classes/java/util/TreeMap.java lines 313, 988, and 1182,
using `@SideEffectFree` at lines 988 and 1182 where appropriate. Keep existing
`@Pure` annotations and method behavior unchanged.

In `@src/java.base/share/classes/java/util/DualPivotQuicksort.java`:
- Around line 186-187: Update all four Sorter-based sort overloads in
src/java.base/share/classes/java/util/DualPivotQuicksort.java at lines 186-187,
942-943, 2490-2491, and 3298-3299: include both arguments in `@SideEffectsOnly`,
and bind low/high to the array parameter (`#2`) rather than the Sorter parameter
(`#1`). Apply the identical annotation correction to the int[], long[], float[],
and double[] overloads.

In `@src/java.base/share/classes/java/util/LinkedHashSet.java`:
- Around line 333-335: Replace the mutator annotations on
LinkedHashSet.reversed() in
src/java.base/share/classes/java/util/LinkedHashSet.java:333-335 with
`@SideEffectFree`. Apply the same annotation change to TreeSet.reversed() in
src/java.base/share/classes/java/util/TreeSet.java:222-224, removing
`@SideEffectsOnly`("this") and `@DoesNotUnrefineReceiver`("modifiability") at both
sites.

In `@src/java.base/share/classes/java/util/Queue.java`:
- Line 235: Remove the contradictory `@SideEffectsOnly`("this") annotation from
the Queue.peek() method, preserving its existing `@Pure` annotation and
non-mutating behavior.

In `@src/java.base/share/classes/java/util/SortedMap.java`:
- Around line 351-353: Update SortedMap.reversed() to replace
`@SideEffectsOnly`("this") and `@DoesNotUnrefineReceiver`("modifiability") with
`@SideEffectFree`, matching the annotations used by other view-creating methods
such as subMap and headMap.

In `@src/java.base/share/classes/java/util/SortedSet.java`:
- Around line 403-404: Update the annotations on the SortedSet.reversed()
view-factory method: replace `@SideEffectsOnly`("this") with `@SideEffectFree` and
remove the redundant `@DoesNotUnrefineReceiver`("modifiability") annotation,
matching the annotation pattern used by subSet and headSet.

---

Outside diff comments:
In `@src/java.base/share/classes/java/util/Collections.java`:
- Around line 1204-1215: Remove `@SideEffectsOnly`("this") and
`@DoesNotUnrefineReceiver`("modifiability") from the read-only methods in
Collections.java: stream() and parallelStream() at lines 1204-1215, reversed()
at 1271-1275 and 1401-1405, subSet(), headSet(), and tailSet() at 1450-1464,
descendingSet(), subSet(), headSet(), and tailSet() at 1550-1577, and
listIterator(int) at 1671-1673. Leave their existing implementations and other
annotations unchanged.

In `@src/java.base/share/classes/java/util/concurrent/BlockingQueue.java`:
- Around line 380-409: Update both drainTo overloads in BlockingQueue so their
`@SideEffectsOnly` annotations include both the receiver and collection argument
c, using the argument-expression target form "`#1`". Leave the existing
`@DoesNotUnrefineReceiver` annotations and method signatures unchanged.

In `@src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java`:
- Around line 1125-1138: Update the `@SideEffectsOnly` annotations on both drainTo
overloads in SynchronousQueue to include the collection parameter alongside
"this" (for example, "this" and "`#1`"), so the mutation performed by c.add(e) is
correctly tracked.

In `@src/java.base/share/classes/java/util/regex/Matcher.java`:
- Around line 1359-1369: Update the `@SideEffectsOnly` annotations on the affected
iterator methods to include both the iterator receiver and its enclosing
collection instance: add Matcher.this in
src/java.base/share/classes/java/util/regex/Matcher.java:1359-1369,
RegularEnumSet.this in
src/java.base/share/classes/java/util/RegularEnumSet.java:138-145, and
PriorityQueue.this in
src/java.base/share/classes/java/util/PriorityQueue.java:572-594.

In `@src/java.base/share/classes/sun/net/www/HeaderParser.java`:
- Around line 212-216: Update HeaderParser.next() to check whether the iterator
is exhausted before indexing tab, and throw NoSuchElementException when index
has reached the available entries. Preserve the existing return and
index-advance behavior for valid elements.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 99f555c6-6920-448f-91af-ac1798aa1ab4

📥 Commits

Reviewing files that changed from the base of the PR and between 0e5bddd and 21c0697.

⛔ Files ignored due to path filters (1)
  • checker-qual.jar is excluded by !**/*.jar
📒 Files selected for processing (122)
  • README.md
  • src/java.base/share/classes/java/io/BufferedReader.java
  • src/java.base/share/classes/java/lang/AbstractStringBuilder.java
  • src/java.base/share/classes/java/lang/CharSequence.java
  • src/java.base/share/classes/java/lang/StackStreamFactory.java
  • src/java.base/share/classes/java/lang/String.java
  • src/java.base/share/classes/java/lang/StringBuffer.java
  • src/java.base/share/classes/java/lang/StringBuilder.java
  • src/java.base/share/classes/java/lang/StringLatin1.java
  • src/java.base/share/classes/java/lang/StringUTF16.java
  • src/java.base/share/classes/java/lang/invoke/AbstractConstantGroup.java
  • src/java.base/share/classes/java/net/URL.java
  • src/java.base/share/classes/java/nio/charset/Charset.java
  • src/java.base/share/classes/java/nio/file/FileTreeIterator.java
  • src/java.base/share/classes/java/nio/file/Files.java
  • src/java.base/share/classes/java/nio/file/Path.java
  • src/java.base/share/classes/java/text/EntryPair.java
  • src/java.base/share/classes/java/util/AbstractCollection.java
  • src/java.base/share/classes/java/util/AbstractList.java
  • src/java.base/share/classes/java/util/AbstractMap.java
  • src/java.base/share/classes/java/util/AbstractQueue.java
  • src/java.base/share/classes/java/util/AbstractSequentialList.java
  • src/java.base/share/classes/java/util/AbstractSet.java
  • src/java.base/share/classes/java/util/ArrayDeque.java
  • src/java.base/share/classes/java/util/ArrayList.java
  • src/java.base/share/classes/java/util/Arrays.java
  • src/java.base/share/classes/java/util/BitSet.java
  • src/java.base/share/classes/java/util/Collection.java
  • src/java.base/share/classes/java/util/Collections.java
  • src/java.base/share/classes/java/util/ComparableTimSort.java
  • src/java.base/share/classes/java/util/Deque.java
  • src/java.base/share/classes/java/util/DualPivotQuicksort.java
  • src/java.base/share/classes/java/util/EnumMap.java
  • src/java.base/share/classes/java/util/EnumSet.java
  • src/java.base/share/classes/java/util/Enumeration.java
  • src/java.base/share/classes/java/util/HashMap.java
  • src/java.base/share/classes/java/util/HashSet.java
  • src/java.base/share/classes/java/util/Hashtable.java
  • src/java.base/share/classes/java/util/IdentityHashMap.java
  • src/java.base/share/classes/java/util/ImmutableCollections.java
  • src/java.base/share/classes/java/util/Iterator.java
  • src/java.base/share/classes/java/util/JumboEnumSet.java
  • src/java.base/share/classes/java/util/LinkedHashMap.java
  • src/java.base/share/classes/java/util/LinkedHashSet.java
  • src/java.base/share/classes/java/util/LinkedList.java
  • src/java.base/share/classes/java/util/List.java
  • src/java.base/share/classes/java/util/ListIterator.java
  • src/java.base/share/classes/java/util/Map.java
  • src/java.base/share/classes/java/util/NavigableMap.java
  • src/java.base/share/classes/java/util/NavigableSet.java
  • src/java.base/share/classes/java/util/PrimitiveIterator.java
  • src/java.base/share/classes/java/util/PriorityQueue.java
  • src/java.base/share/classes/java/util/Properties.java
  • src/java.base/share/classes/java/util/Queue.java
  • src/java.base/share/classes/java/util/RegularEnumSet.java
  • src/java.base/share/classes/java/util/ReverseOrderDequeView.java
  • src/java.base/share/classes/java/util/ReverseOrderListView.java
  • src/java.base/share/classes/java/util/ReverseOrderSortedSetView.java
  • src/java.base/share/classes/java/util/Scanner.java
  • src/java.base/share/classes/java/util/SequencedCollection.java
  • src/java.base/share/classes/java/util/SequencedMap.java
  • src/java.base/share/classes/java/util/SequencedSet.java
  • src/java.base/share/classes/java/util/ServiceLoader.java
  • src/java.base/share/classes/java/util/Set.java
  • src/java.base/share/classes/java/util/SortedMap.java
  • src/java.base/share/classes/java/util/SortedSet.java
  • src/java.base/share/classes/java/util/Spliterators.java
  • src/java.base/share/classes/java/util/Stack.java
  • src/java.base/share/classes/java/util/TreeMap.java
  • src/java.base/share/classes/java/util/TreeSet.java
  • src/java.base/share/classes/java/util/Vector.java
  • src/java.base/share/classes/java/util/WeakHashMap.java
  • src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
  • src/java.base/share/classes/java/util/concurrent/BlockingDeque.java
  • src/java.base/share/classes/java/util/concurrent/BlockingQueue.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java
  • src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
  • src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java
  • src/java.base/share/classes/java/util/concurrent/DelayQueue.java
  • src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
  • src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
  • src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
  • src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
  • src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java
  • src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java
  • src/java.base/share/classes/java/util/jar/Attributes.java
  • src/java.base/share/classes/java/util/regex/Matcher.java
  • src/java.base/share/classes/java/util/regex/Pattern.java
  • src/java.base/share/classes/java/util/zip/ZipFile.java
  • src/java.base/share/classes/javax/security/auth/Subject.java
  • src/java.base/share/classes/jdk/internal/icu/text/Replaceable.java
  • src/java.base/share/classes/jdk/internal/icu/text/ReplaceableString.java
  • src/java.base/share/classes/org/checkerframework/checker/builder/qual/CalledMethods.java
  • src/java.base/share/classes/org/checkerframework/checker/formatter/qual/ConversionCategory.java
  • src/java.base/share/classes/org/checkerframework/checker/formatter/qual/FormatBottom.java
  • src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nConversionCategory.java
  • src/java.base/share/classes/org/checkerframework/checker/i18nformatter/qual/I18nFormatBottom.java
  • src/java.base/share/classes/org/checkerframework/checker/index/qual/IndexOrHigh.java
  • src/java.base/share/classes/org/checkerframework/checker/index/qual/LengthOf.java
  • src/java.base/share/classes/org/checkerframework/checker/interning/qual/InternedDistinct.java
  • src/java.base/share/classes/org/checkerframework/checker/nonempty/qual/EnsuresNonEmptyIf.java
  • src/java.base/share/classes/org/checkerframework/checker/optional/qual/RequiresPresent.java
  • src/java.base/share/classes/org/checkerframework/checker/regex/qual/RegexBottom.java
  • src/java.base/share/classes/org/checkerframework/checker/signature/qual/README.md
  • src/java.base/share/classes/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java
  • src/java.base/share/classes/org/checkerframework/common/aliasing/qual/NonLeaked.java
  • src/java.base/share/classes/org/checkerframework/common/returnsreceiver/qual/UnknownThis.java
  • src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectFree.java
  • src/java.base/share/classes/org/checkerframework/dataflow/qual/SideEffectsOnly.java
  • src/java.base/share/classes/org/checkerframework/framework/qual/ConditionalPostconditionAnnotation.java
  • src/java.base/share/classes/org/checkerframework/framework/qual/DoesNotUnrefineReceiver.java
  • src/java.base/share/classes/sun/net/www/HeaderParser.java
  • src/java.base/share/classes/sun/net/www/MessageHeader.java
  • src/java.base/share/classes/sun/security/jca/ProviderList.java
  • src/java.base/share/classes/sun/util/PreHashedMap.java
  • src/java.base/share/classes/sun/util/locale/StringTokenIterator.java
  • src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java

Comment thread src/java.base/share/classes/java/lang/StringBuilder.java
Comment thread src/java.base/share/classes/java/util/concurrent/DelayQueue.java Outdated
Comment thread src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java Outdated
Comment thread src/java.base/share/classes/java/util/Deque.java Outdated
Comment thread src/java.base/share/classes/java/util/DualPivotQuicksort.java
Comment thread src/java.base/share/classes/java/util/LinkedHashSet.java Outdated
Comment thread src/java.base/share/classes/java/util/Queue.java Outdated
Comment thread src/java.base/share/classes/java/util/SortedMap.java Outdated
Comment thread src/java.base/share/classes/java/util/SortedSet.java Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java (1)

913-914: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add @DoesNotUnrefineReceiver("modifiability") to Itr.next.
PriorityBlockingQueue.Itr.next is side-effecting and should match the same receiver refinement contract used by DelayQueue and LinkedBlockingQueue.

Suggested fix
     `@SideEffectsOnly`("this")
+    `@DoesNotUnrefineReceiver`("modifiability")
     public E next(`@NonEmpty` Itr this) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java`
around lines 913 - 914, Add `@DoesNotUnrefineReceiver`("modifiability") to
PriorityBlockingQueue.Itr.next alongside its existing `@SideEffectsOnly`("this")
annotation, matching the receiver refinement contract used by DelayQueue and
LinkedBlockingQueue.
src/java.base/share/classes/java/util/Collections.java (1)

904-906: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fix invalid receiver annotations on a static method.

The replaceAll method is static and therefore has no receiver (this). The @SideEffectsOnly("this") and @DoesNotUnrefineReceiver annotations are intended for instance methods and are invalid here. The method mutates its first parameter (list), so the correct annotation is @SideEffectsOnly("#1").

🐛 Proposed fix
-    `@SideEffectsOnly`("this")
-    `@DoesNotUnrefineReceiver`("modifiability")
+    `@SideEffectsOnly`("`#1`")
     public static <T> boolean replaceAll(List<T> list, `@Nullable` T oldVal, T newVal) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/Collections.java` around lines 904 -
906, Update the static Collections.replaceAll method annotations to reference
its first parameter rather than the nonexistent receiver: change the side-effect
target to "`#1`" and remove or replace the receiver-specific
`@DoesNotUnrefineReceiver` annotation according to the project’s
parameter-annotation conventions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/java.base/share/classes/java/util/Collections.java`:
- Around line 904-906: Update the static Collections.replaceAll method
annotations to reference its first parameter rather than the nonexistent
receiver: change the side-effect target to "`#1`" and remove or replace the
receiver-specific `@DoesNotUnrefineReceiver` annotation according to the project’s
parameter-annotation conventions.

In `@src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java`:
- Around line 913-914: Add `@DoesNotUnrefineReceiver`("modifiability") to
PriorityBlockingQueue.Itr.next alongside its existing `@SideEffectsOnly`("this")
annotation, matching the receiver refinement contract used by DelayQueue and
LinkedBlockingQueue.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a8ae828d-ce9b-4c74-a888-6cf4df156d28

📥 Commits

Reviewing files that changed from the base of the PR and between 21c0697 and eeaace3.

📒 Files selected for processing (10)
  • src/java.base/share/classes/java/lang/StringBuilder.java
  • src/java.base/share/classes/java/util/Collections.java
  • src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
  • src/java.base/share/classes/java/util/concurrent/BlockingQueue.java
  • src/java.base/share/classes/java/util/concurrent/DelayQueue.java
  • src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
  • src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
  • src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
  • src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
  • src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (9)
src/java.base/share/classes/java/util/ArrayDeque.java (2)

347-349: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not claim these methods only modify the deque.

addAll delegates through caller-provided iteration, removeFirstOccurrence()/removeLastOccurrence()/remove() call o.equals(...), and removeIf()/removeAll()/retainAll() call caller-supplied code (filter.test(...) or c.contains(e)). Those can mutate receiver arguments, c, or other reachable state, so @SideEffectsOnly("this") is too narrow for these contracts. Remove the annotations or include the affected arguments/predicates in the expression list if it is supported in the local Checker Framework setup.

Also applies to: 485-487, 515-517, 980-982, 990-992, 1000-1002, 1118-1120

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/ArrayDeque.java` around lines 347 -
349, Remove the `@SideEffectsOnly`("this") annotations from ArrayDeque methods
addAll, removeFirstOccurrence, removeLastOccurrence, remove, removeIf,
removeAll, and retainAll, or expand their expressions to include all
caller-provided arguments and predicates if supported by the local Checker
Framework. Do not leave these methods claiming side effects are limited to the
deque.

Source: MCP tools


787-789: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Account for the enclosing deque mutation in iterator remove().

delete(lastRet) mutates the enclosing ArrayDeque (elements, head, and/or tail), while @SideEffectsOnly("this") only permits side effects on DeqIterator. Include the enclosing receiver in the annotation, or remove it if that expression syntax is not supported for nested classes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/ArrayDeque.java` around lines 787 -
789, Update the iterator remove() method’s `@SideEffectsOnly` annotation to permit
mutation of the enclosing ArrayDeque receiver in addition to DeqIterator, using
the supported nested-receiver expression; if that syntax is unsupported, remove
the annotation rather than retaining an incorrect contract. Keep delete(lastRet)
behavior unchanged.

Source: MCP tools

src/java.base/share/classes/java/util/Arrays.java (1)

1077-1078: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Remove @SideEffectsOnly("#1") from user-controlled sorting callbacks.

SideEffectsOnly records an upper bound on the expressions a method may change; calling user-controlled Comparable.compareTo or Comparator.compare can mutate arbitrary state beyond #1. The side-effect annotation is unsound for lines 1077, 1143, 1268, and 1341 unless callback effects are explicitly excluded/defined.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/Arrays.java` around lines 1077 - 1078,
Remove the `@SideEffectsOnly`("`#1`") annotation from the affected Arrays.sort
overloads, including the overloads near the identified sort methods at lines
1077, 1143, 1268, and 1341. Leave the sorting implementations and callback
behavior unchanged, and ensure no user-controlled Comparable.compareTo or
Comparator.compare invocation remains annotated with this unsound side-effect
bound.
src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java (3)

1268-1282: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

COWIterator.previous() is missing @DoesNotUnrefineReceiver("modifiability").

next() (lines 1267-1274) and the three throwing methods remove()/set()/add() (lines 1299-1325) — all touched by this same diff hunk — carry both @SideEffectsOnly("this") and @DoesNotUnrefineReceiver("modifiability"). previous() only got @SideEffectsOnly("this") activated, breaking the symmetry with next() for what is otherwise an identical cursor-mutation operation.

🐛 Proposed fix
         `@SuppressWarnings`("unchecked")
         `@SideEffectsOnly`("this")
+        `@DoesNotUnrefineReceiver`("modifiability")
         public E previous() {
             if (! hasPrevious())
                 throw new NoSuchElementException();
             return (E) snapshot[--cursor];
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java`
around lines 1268 - 1282, Add `@DoesNotUnrefineReceiver`("modifiability") to
COWIterator.previous(), matching the existing annotations on next() and the
throwing iterator mutation methods while retaining `@SideEffectsOnly`("this").

2013-2018: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reversed.add(E), add(int, E), addFirst, addLast all drop @EnsuresNonEmpty("this").

See consolidated cross-file comment for the fix.

Also applies to: 2155-2173

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java`
around lines 2013 - 2018, Restore `@EnsuresNonEmpty`("this") on Reversed.add(E)
and the corresponding add(int, E), addFirst, and addLast methods around the
referenced symbols, preserving the existing mutation behavior while declaring
that each successful operation leaves this collection non-empty.

1602-1626: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

COWSubList.add(int, E), addFirst, addLast drop @EnsuresNonEmpty("this") that the sibling add(E) (line 1589) and the outer CopyOnWriteArrayList equivalents keep.

See consolidated cross-file comment for the fix.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java`
around lines 1602 - 1626, Add `@EnsuresNonEmpty`("this") to COWSubList.add(int,
E), addFirst(E), and addLast(E), matching the existing contract annotations on
sibling add(E) and the outer CopyOnWriteArrayList methods.
src/java.base/share/classes/java/util/LinkedList.java (2)

1628-1641: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

ReverseOrderLinkedListView.add(int, E) and .add(E) drop the @EnsuresNonEmpty("this") postcondition present on the List contract.

List.add(int, E) and List.add(E) (this file's main-class overrides too) both declare @EnsuresNonEmpty("this") since a normal return always increases size. Here the reverse-view overrides only got @SideEffectsOnly("this")/@DoesNotUnrefineReceiver("modifiability") activated, silently dropping the postcondition. See consolidated comment for the fix and other affected sites.

Also applies to: 1664-1680

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/LinkedList.java` around lines 1628 -
1641, The reverse-view methods add(int, E) and add(E) must preserve the List
contract’s `@EnsuresNonEmpty`("this") postcondition. Add that annotation to both
overrides in ReverseOrderLinkedListView, alongside their existing side-effect
and receiver annotations, without changing their delegation behavior.

1692-1702: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

ReverseOrderLinkedListView.addLast/addFirst also drop @EnsuresNonEmpty("this").

Same gap as add(int, E)/add(E) above — List.addFirst/addLast declare @EnsuresNonEmpty("this"), but these overrides only carry @SideEffectsOnly("this"). See consolidated comment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/LinkedList.java` around lines 1692 -
1702, Update ReverseOrderLinkedListView.addLast and addFirst to include the
`@EnsuresNonEmpty`("this") contract alongside their existing annotations, matching
the List.addLast/addFirst API declarations and the related add methods.
src/java.base/share/classes/java/util/NavigableSet.java (1)

207-208: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Mark descendingSet() as side-effect-free.

The returned NavigableSet is a reverse-order view and does not mutate the receiver, so src/java.base/share/classes/java/util/NavigableSet.java:207-208 should use @SideEffectFree and @DoesNotUnrefineReceiver("modifiability") instead of @SideEffectsOnly("this"), matching descendingIterator(), reversed(), and the existing view-factory methods in this interface.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/NavigableSet.java` around lines 207 -
208, Update the annotations on NavigableSet.descendingSet() by replacing
`@SideEffectsOnly`("this") with `@SideEffectFree` while retaining
`@DoesNotUnrefineReceiver`("modifiability"), matching the side-effect contract
used by the related view-factory methods.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/java.base/share/classes/java/util/ArrayDeque.java`:
- Around line 347-349: Remove the `@SideEffectsOnly`("this") annotations from
ArrayDeque methods addAll, removeFirstOccurrence, removeLastOccurrence, remove,
removeIf, removeAll, and retainAll, or expand their expressions to include all
caller-provided arguments and predicates if supported by the local Checker
Framework. Do not leave these methods claiming side effects are limited to the
deque.
- Around line 787-789: Update the iterator remove() method’s `@SideEffectsOnly`
annotation to permit mutation of the enclosing ArrayDeque receiver in addition
to DeqIterator, using the supported nested-receiver expression; if that syntax
is unsupported, remove the annotation rather than retaining an incorrect
contract. Keep delete(lastRet) behavior unchanged.

In `@src/java.base/share/classes/java/util/Arrays.java`:
- Around line 1077-1078: Remove the `@SideEffectsOnly`("`#1`") annotation from the
affected Arrays.sort overloads, including the overloads near the identified sort
methods at lines 1077, 1143, 1268, and 1341. Leave the sorting implementations
and callback behavior unchanged, and ensure no user-controlled
Comparable.compareTo or Comparator.compare invocation remains annotated with
this unsound side-effect bound.

In `@src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java`:
- Around line 1268-1282: Add `@DoesNotUnrefineReceiver`("modifiability") to
COWIterator.previous(), matching the existing annotations on next() and the
throwing iterator mutation methods while retaining `@SideEffectsOnly`("this").
- Around line 2013-2018: Restore `@EnsuresNonEmpty`("this") on Reversed.add(E) and
the corresponding add(int, E), addFirst, and addLast methods around the
referenced symbols, preserving the existing mutation behavior while declaring
that each successful operation leaves this collection non-empty.
- Around line 1602-1626: Add `@EnsuresNonEmpty`("this") to COWSubList.add(int, E),
addFirst(E), and addLast(E), matching the existing contract annotations on
sibling add(E) and the outer CopyOnWriteArrayList methods.

In `@src/java.base/share/classes/java/util/LinkedList.java`:
- Around line 1628-1641: The reverse-view methods add(int, E) and add(E) must
preserve the List contract’s `@EnsuresNonEmpty`("this") postcondition. Add that
annotation to both overrides in ReverseOrderLinkedListView, alongside their
existing side-effect and receiver annotations, without changing their delegation
behavior.
- Around line 1692-1702: Update ReverseOrderLinkedListView.addLast and addFirst
to include the `@EnsuresNonEmpty`("this") contract alongside their existing
annotations, matching the List.addLast/addFirst API declarations and the related
add methods.

In `@src/java.base/share/classes/java/util/NavigableSet.java`:
- Around line 207-208: Update the annotations on NavigableSet.descendingSet() by
replacing `@SideEffectsOnly`("this") with `@SideEffectFree` while retaining
`@DoesNotUnrefineReceiver`("modifiability"), matching the side-effect contract
used by the related view-factory methods.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: eeeea339-2ea5-4bd7-8dcd-c9bdbc5185d1

📥 Commits

Reviewing files that changed from the base of the PR and between eeaace3 and f049d9c.

📒 Files selected for processing (33)
  • src/java.base/share/classes/java/util/AbstractCollection.java
  • src/java.base/share/classes/java/util/ArrayDeque.java
  • src/java.base/share/classes/java/util/ArrayList.java
  • src/java.base/share/classes/java/util/Arrays.java
  • src/java.base/share/classes/java/util/Collections.java
  • src/java.base/share/classes/java/util/Comparator.java
  • src/java.base/share/classes/java/util/Comparators.java
  • src/java.base/share/classes/java/util/Deque.java
  • src/java.base/share/classes/java/util/EnumMap.java
  • src/java.base/share/classes/java/util/ImmutableCollections.java
  • src/java.base/share/classes/java/util/LinkedHashMap.java
  • src/java.base/share/classes/java/util/LinkedHashSet.java
  • src/java.base/share/classes/java/util/LinkedList.java
  • src/java.base/share/classes/java/util/List.java
  • src/java.base/share/classes/java/util/NavigableMap.java
  • src/java.base/share/classes/java/util/NavigableSet.java
  • src/java.base/share/classes/java/util/Queue.java
  • src/java.base/share/classes/java/util/ReverseOrderDequeView.java
  • src/java.base/share/classes/java/util/ReverseOrderSortedMapView.java
  • src/java.base/share/classes/java/util/ReverseOrderSortedSetView.java
  • src/java.base/share/classes/java/util/SequencedCollection.java
  • src/java.base/share/classes/java/util/SequencedMap.java
  • src/java.base/share/classes/java/util/SequencedSet.java
  • src/java.base/share/classes/java/util/SortedMap.java
  • src/java.base/share/classes/java/util/SortedSet.java
  • src/java.base/share/classes/java/util/TreeMap.java
  • src/java.base/share/classes/java/util/Vector.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java
  • src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
  • src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
💤 Files with no reviewable changes (6)
  • src/java.base/share/classes/java/util/Queue.java
  • src/java.base/share/classes/java/util/EnumMap.java
  • src/java.base/share/classes/java/util/AbstractCollection.java
  • src/java.base/share/classes/java/util/ArrayList.java
  • src/java.base/share/classes/java/util/Vector.java
  • src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/java.base/share/classes/java/util/Enumeration.java (1)

138-141: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Use the enclosing Enumeration receiver in the adapter contract.

@SideEffectsOnly("this") limits mutations to the anonymous Iterator object. This override delegates to Enumeration.nextElement(), which changes the enclosing Enumeration state, not the adapter object.

Specify the enclosing receiver, or change the contract only if the adapter is intentionally modeled as owning iterator state. Add a Checker Framework test for this path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/java.base/share/classes/java/util/Enumeration.java` around lines 138 -
141, Update the `next` override in the `Enumeration`-to-`Iterator` adapter so
its `@SideEffectsOnly` contract names the enclosing `Enumeration` receiver whose
state is mutated, rather than only the anonymous iterator adapter. Preserve the
existing `nextElement()` delegation and add a Checker Framework test covering
this receiver-effect path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/java.base/share/classes/java/util/Enumeration.java`:
- Around line 138-141: Update the `next` override in the
`Enumeration`-to-`Iterator` adapter so its `@SideEffectsOnly` contract names the
enclosing `Enumeration` receiver whose state is mutated, rather than only the
anonymous iterator adapter. Preserve the existing `nextElement()` delegation and
add a Checker Framework test covering this receiver-effect path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 31efa1b2-1361-4237-8111-5703f6c10fd1

📥 Commits

Reviewing files that changed from the base of the PR and between f049d9c and d4a2682.

📒 Files selected for processing (1)
  • src/java.base/share/classes/java/util/Enumeration.java

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.

1 participant