Skip to content

track wrapped iterator removability in ListIteratorWrapper - #746

Open
rootvector2 wants to merge 1 commit into
apache:masterfrom
rootvector2:listiteratorwrapper-remove-state
Open

rootvector2 wants to merge 1 commit into
apache:masterfrom
rootvector2:listiteratorwrapper-remove-state

Conversation

@rootvector2

Copy link
Copy Markdown
Contributor

ListIteratorWrapper.remove() gates on a removeState flag that next() sets only in the branch that pulls a fresh element from the wrapped iterator, and previous() recomputes it from the cursor position alone, so walking back into the element cache with previous() and then forward again until the cursor is level with the wrapped iterator leaves the flag false and remove() throws IllegalStateException for a removal java.util.ListIterator requires to succeed, while reset() rewinds the cursor without clearing the flag so next(), reset(), remove() deletes an element the remove() javadoc says it must reject; the flag is now derived from whether the element last returned by the wrapped iterator can still be removed from it. Found with a randomized differential test of the library's list iterators against java.util.ArrayList.listIterator(), which also confirmed ListIteratorWrapper is the only one that caches a plain Iterator this way (the siblings either delegate to a real ListIterator or reject remove() outright).

  • Read the contribution guidelines for this project.
  • Read the ASF Generative Tooling Guidance if you use Artificial Intelligence (AI).
  • I used AI to create any part of, or all of, this pull request. Which AI tool was used to create this pull request, and to what extent did it contribute? Claude Code, used to run the differential test that located the defect and to draft this patch and the two regression tests.
  • Run a successful build using the default Maven goal with mvn; that's mvn on the command line by itself.
  • Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process.

next() set removeState only when it pulled a fresh element from the wrapped iterator and previous() derived it from the cursor position alone, so remove() rejected a legal removal after reading back out of the element cache, and reset() left the flag set so remove() deleted an element it had to reject.
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