[PATCH v3] rust: rbtree: document peek_next() on the immutable cursor

From: Juan Patricio Marchetto

Date: Fri Jul 31 2026 - 17:56:48 EST


The immutable Cursor has a single example, covering cursor_front() and
current(). Its peek_next() has none: the only worked example of peeking
belongs to CursorMut.

That leaves the most common reason to hold an immutable cursor
undocumented. cursor_lower_bound() stops on an exact match, so a caller
looking for the first key strictly greater than the one it supplied has
to peek past it. When the key was absent the cursor already holds the
answer, and peeking there returns its successor instead, skipping an
element.

Document both branches, and the case where the looked-up key is the
largest in the tree and has no successor.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Juan Patricio Marchetto <juanpatriciomarchetto@xxxxxxxxx>
---

Notes:
v3:
- Move the example from the Cursor type documentation onto
Cursor::peek_next(), adding an "# Examples" heading and adapting
the intro sentence to the new context (Gary Guo).
- Reformat the doctest import to the kernel vertical import style
(Sashiko review of v2).
- Verified with rust_doctests_kernel under ARCH=um: 321/321.

v2: v1 documented only the exact-match branch, so the idiom as written
skipped an element whenever the looked-up key was absent. The example now
covers both branches and uses a four-element tree so the skipped element
is visible. Reported by the Sashiko review of v1.

v2: https://lore.kernel.org/r/20260729023420.1323906-1-juanpatriciomarchetto@xxxxxxxxx
v1: https://lore.kernel.org/r/20260729014344.1244809-1-juanpatriciomarchetto@xxxxxxxxx

rust/kernel/rbtree.rs | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)

diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs
index 6fbd579d4a4..42f946a9bd0 100644
--- a/rust/kernel/rbtree.rs
+++ b/rust/kernel/rbtree.rs
@@ -856,6 +856,47 @@ pub fn peek_prev(&self) -> Option<(&K, &V)> {
}

/// Access the next node without moving the cursor.
+ ///
+ /// # Examples
+ ///
+ /// Peeking completes a lookup for the first key strictly greater than a given
+ /// one. [`RBTree::cursor_lower_bound`] stops on an exact match, so the peek is
+ /// needed only when the key was present: when it was absent the cursor already
+ /// holds the answer, and peeking there skips an element instead.
+ ///
+ /// ```
+ /// use kernel::{
+ /// alloc::flags,
+ /// rbtree::RBTree, //
+ /// };
+ ///
+ /// // Create a new tree.
+ /// let mut tree = RBTree::new();
+ ///
+ /// // Insert four elements.
+ /// tree.try_create_and_insert(10, 100, flags::GFP_KERNEL)?;
+ /// tree.try_create_and_insert(20, 200, flags::GFP_KERNEL)?;
+ /// tree.try_create_and_insert(30, 300, flags::GFP_KERNEL)?;
+ /// tree.try_create_and_insert(40, 400, flags::GFP_KERNEL)?;
+ ///
+ /// // 20 is present, so the cursor stops on the key the caller already has and the
+ /// // successor is one peek away.
+ /// let cursor = tree.cursor_lower_bound(&20).unwrap();
+ /// assert_eq!(cursor.current(), (&20, &200));
+ /// assert_eq!(cursor.peek_next().unwrap(), (&30, &300));
+ ///
+ /// // 25 is absent, so the cursor already sits on the answer. Peeking from here
+ /// // returns 40 and skips 30.
+ /// let cursor = tree.cursor_lower_bound(&25).unwrap();
+ /// assert_eq!(cursor.current(), (&30, &300));
+ /// assert_eq!(cursor.peek_next().unwrap(), (&40, &400));
+ ///
+ /// // The largest key has no successor.
+ /// let cursor = tree.cursor_lower_bound(&40).unwrap();
+ /// assert!(cursor.peek_next().is_none());
+ ///
+ /// # Ok::<(), Error>(())
+ /// ```
pub fn peek_next(&self) -> Option<(&K, &V)> {
self.peek(Direction::Next)
}

base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
--
2.43.0