Fix LinkedList::CursorMut::pop_front to correctly update index
When `pop_front` was called while the cursor pointed to the front element, `move_next` incremented the index but it was never decremented afterwards, causing the index to incorrectly report 1 instead of 0. Always decrement the index after popping from front using `saturating_sub` to handle edge cases safely.
This commit is contained in:
parent
31010ca61c
commit
901fe3f804
2 changed files with 58 additions and 2 deletions
|
|
@ -1855,9 +1855,11 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
|
|||
// node at index 0, which is expected.
|
||||
if self.list.head == self.current {
|
||||
self.move_next();
|
||||
} else {
|
||||
self.index -= 1;
|
||||
}
|
||||
// An element was removed before (or at) our current position, so
|
||||
// the index must be decremented. `saturating_sub` handles the
|
||||
// ghost node case where index could be 0.
|
||||
self.index = self.index.saturating_sub(1);
|
||||
self.list.pop_front()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -748,6 +748,60 @@ fn test_cursor_pop_front_back() {
|
|||
assert_eq!(c.index, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cursor_pop_front_index() {
|
||||
// Regression test for issue #147616: `pop_front` was not correctly
|
||||
// updating the cursor index when the cursor was pointing to the front.
|
||||
|
||||
// Test case 1: pop_front when cursor is not at front, then at front
|
||||
let mut ll: LinkedList<u32> = LinkedList::new();
|
||||
ll.extend(&[0, 1, 2]);
|
||||
let mut c = ll.cursor_front_mut();
|
||||
|
||||
c.move_next();
|
||||
assert_eq!(c.index(), Some(1));
|
||||
assert_eq!(c.current(), Some(&mut 1));
|
||||
|
||||
// Pop front when cursor is not at front - index should decrement
|
||||
c.pop_front();
|
||||
assert_eq!(c.index(), Some(0));
|
||||
assert_eq!(c.current(), Some(&mut 1));
|
||||
|
||||
// Now cursor is at front, pop_front again - index should remain 0
|
||||
c.pop_front();
|
||||
assert_eq!(c.index(), Some(0));
|
||||
assert_eq!(c.current(), Some(&mut 2));
|
||||
check_links(&ll);
|
||||
|
||||
// Test case 2: minimal reproduction - cursor at front, pop_front
|
||||
let mut ll: LinkedList<u32> = LinkedList::new();
|
||||
ll.extend(&[0, 1]);
|
||||
let mut c = ll.cursor_front_mut();
|
||||
|
||||
assert_eq!(c.index(), Some(0));
|
||||
assert_eq!(c.current(), Some(&mut 0));
|
||||
|
||||
// Pop front when cursor is at front - should move to next and index stays 0
|
||||
c.pop_front();
|
||||
assert_eq!(c.index(), Some(0));
|
||||
assert_eq!(c.current(), Some(&mut 1));
|
||||
check_links(&ll);
|
||||
|
||||
// Test case 3: single element list
|
||||
let mut ll: LinkedList<u32> = LinkedList::new();
|
||||
ll.push_back(42);
|
||||
let mut c = ll.cursor_front_mut();
|
||||
|
||||
assert_eq!(c.index(), Some(0));
|
||||
assert_eq!(c.current(), Some(&mut 42));
|
||||
|
||||
// Pop the only element - cursor should be at ghost node with index 0
|
||||
c.pop_front();
|
||||
assert_eq!(c.index(), None);
|
||||
assert_eq!(c.current(), None);
|
||||
check_links(&ll);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extend_ref() {
|
||||
let mut a = LinkedList::new();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue