-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Description
When using linked_list::CursorMut, calling pop_front while the cursor is positioned at the front node does not update the index correctly. After popping the front element, I expect the index to reflect the new position of the current element, but instead it remains unchanged or becomes inconsistent.
example 1
#![feature(linked_list_cursors)]
use std::collections::LinkedList;
fn main() {
let mut l = LinkedList::from_iter([0, 1, 2]);
let mut c = l.cursor_front_mut();
c.move_next();
println!("index: {:?} current: {:?}", c.index(), c.current()); // index: Some(1), current: Some(1)
// index is decremented since we removed an item before the current one
c.pop_front();
println!("index: {:?} current: {:?}", c.index(), c.current()); // index: Some(0), current: Some(1)
// Unexpected behavior: current is at the front, but index is incremented
c.pop_front();
println!("index: {:?} current: {:?}", c.index(), c.current()); // index: Some(1), current: Some(2), but expected index: Some(0)
}minimal reproduction
#![feature(linked_list_cursors)]
use std::collections::LinkedList;
fn main() {
let mut l = LinkedList::from_iter([0, 1]);
let mut c = l.cursor_front_mut();
println!("index: {:?} current: {:?}", c.index(), c.current()); // index: Some(0), current: Some(0)
// Unexpected behavior: after removing the front (which is also current), index goes at 1
c.pop_front();
println!("index: {:?} current: {:?}", c.index(), c.current()); // index: Some(1), current: Some(1), but expected index: Some(0)
}link to playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=aa3317b89922e9ed623525807c8b90c2
Expected Behavior
When popping the front element and the cursor's current element becomes the new front, index() should return Some(0).
Current Behavior
index() returns a wrong index value (Some(1) in these examples), which is misleading because the cursor is now logically positioned at the new front.
Meta
rustc +nightly --version --verbose:
rustc 1.92.0-nightly (be0ade2b6 2025-10-11)
binary: rustc
commit-hash: be0ade2b602bdfe37a3cc259fcc79e8624dcba94
commit-date: 2025-10-11
host: x86_64-unknown-linux-gnu
release: 1.92.0-nightly
LLVM version: 21.1.2
Proposed Change
The current code: https://github.com/rust-lang/rust/blob/ff6dc928c5e33ce8e65c6911a790b9efcb5ef53a/library/alloc/src/collections/linked_list.rs#L1845C5-L1864C6
My change proposal:
#[unstable(feature = "linked_list_cursors", issue = "58533")]
pub fn pop_front(&mut self) -> Option<T> {
// We can't check if current is empty, we must check the list directly.
// It is possible for `self.current == None` and the list to be
// non-empty.
if self.list.is_empty() {
None
} else {
// We can't point to the node that we pop. Copying the behavior of
// `remove_current`, we move on to the next node in the sequence.
// If the list is of length 1 then we end pointing to the "ghost"
// node at index 0, which is expected.
if self.list.head == self.current {
self.move_next();
}
self.index = self.index.saturating_sub(1);
self.list.pop_front()
}
}If this issue makes sense and the expected behavior above is correct, I’d be happy to open a pull request with the fix.
Thank you for the amazing work you all do on Rust