Repository: rust-lang/rust
File: library/alloc/src/collections/btree/map.rs (Rust)

Code before:
            .next_back_kv()
            // This should be unwrap(), but that doesn't work because NodeRef
            // doesn't implement Debug. The condition is checked above.
            .ok()?
            .remove_kv_tracking(|| emptied_internal_root = true, self.alloc.clone());
        self.current = Some(pos);
        *self.length -= 1;
        if emptied_internal_root {
            // SAFETY: This is safe since current does not point within the now
            // empty root node.
            let root = unsafe { self.root.reborrow().as_mut().unwrap() };
            root.pop_internal_level(self.alloc.clone());
        }
        Some(kv)
    }
}

impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> {
    /// Calls a function with a reference to the next element's key and
    /// ownership of its value. The function is expected to return a value
    /// to write back to the next element's value. The cursor is not
    /// advanced forward.
    ///
    /// If the cursor is at the end of the map then the function is not called
    /// and this essentially does not do anything.
    pub(super) fn with_next(&mut self, f: impl FnOnce(&K, V) -> V) {
        /// Call `f` with the next entry's key and value, replacing the
        /// next entry's value with the returned value. if `f` unwinds,
        /// the next entry is removed.
        /// Equivalent to a more efficient version of:
        /// ```ignore (this is an example equivalent)
        /// if let Some((k, v)) = self.remove_next() {
        ///     let v = f(&k, v);
        ///     // Safety: key is unmodified
        ///     unsafe { self.insert_after_unchecked(k, v) };
        /// }
        /// ```
        struct RemoveNextOnDrop<'a, 'b, K, V, A = Global>
        where
            K: Ord,
            A: Allocator + Clone,
        {
            cursor: &'a mut CursorMut<'b, K, V, A>,
            forget_next: bool,
        }

        impl<K: Ord, V, A: Allocator + Clone> Drop for RemoveNextOnDrop<'_, '_, K, V, A> {
            fn drop(&mut self) {
                if self.forget_next {
                    // Removes the next entry of the Cursor without running
                    // running the destructor on the value (prevents double

Review comment (performance):
since `forget_next_value` and `forget_next_key_and_value` are not sound as currently written since they move already-dropped `K` and `V` values (and maybe drop them again on unwind), and [we can't currently use the `transmute` to `ManuallyDrop` idea](https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/could.20we.20use.20transmute.20tricks.20in.20the.20impl.20of.20BTreeMap.3F/near/573581452), I think the best option for now is to remove `forget_next_*` and change `with_next` to use the simplistic equivalent implementation with a comment that it can be much more optimized in the future:
```rust
if let Some((k, v)) = self.remove_next() {
    let v = f(&k, v);
    // Safety: key is unmodified
    unsafe { self.insert_after_unchecked(k, v) };
}
```

Code after:
    /// The element that was removed is returned. The cursor position is
    /// unchanged (before the removed element).
    #[unstable(feature = "btree_cursors", issue = "107540")]
    pub fn remove_next(&mut self) -> Option<(K, V)> {
        self.inner.remove_next()
    }

    /// Removes the preceding element from the `BTreeMap`.
    ///
    /// The element that was removed is returned. The cursor position is
    /// unchanged (after the removed element).
    #[unstable(feature = "btree_cursors", issue = "107540")]
    pub fn remove_prev(&mut self) -> Option<(K, V)> {
        self.inner.remove_prev()
    }
}

/// Error type returned by [`CursorMut::insert_before`] and
/// [`CursorMut::insert_after`] if the key being inserted is not properly
/// ordered with regards to adjacent keys.
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "btree_cursors", issue = "107540")]
pub struct UnorderedKeyError {}

#[unstable(feature = "btree_cursors", issue = "107540")]
impl fmt::Display for UnorderedKeyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "key is not properly ordered relative to neighbors")
    }
}

#[unstable(feature = "btree_cursors", issue = "107540")]
impl Error for UnorderedKeyError {}

#[cfg(test)]
mod tests;