Amanieu / intrusive-rs

Intrusive collections for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CursorMut::get() should return a mutable reference?

njaard opened this issue · comments

There doesn't seem to be a way to modify the contents of an item in the RBTree.

This is by design: you can't get a &mut T because there may be multiple references to it (e.g. an item has multiple links and is inserted into more than one collection). You should use a Cell/RefCell/UnsafeCell if you need to mutate the contents of an item.

Hi, @Amanieu
I appreciate and understand your design approach. It's a good point to limit accessing &mut T to ensure soundness. However, I believe that providing an unsafe get_mut() method may be necessary for developers. In most situations, a linked list has only one link, and CursorMut can guarantee that there are no multiple mutable references to the list node. Additionally, the rust standard crate CursorMut provides similar methods for accessing mutable references and the intrusive-rs crate can maintain consistency with the standard crate's API.
An proposed code like this:

    /// Returns a mut reference to the object that the cursor is currently
    /// pointing to.
    ///
    /// This returns None if the cursor is currently pointing to the null
    /// object.
    ///
    /// # Safety
    /// The pointing object has and merely has one link.
    #[inline]
    pub unsafe fn get_mut(&mut self) -> Option<&mut <A::PointerOps as PointerOps>::Value> {
        Some(unsafe {
            &mut *(self.list.adapter.get_value(self.current?)
                as *mut <A::PointerOps as PointerOps>::Value)
        })
    }

If you need unsafe mutable access then you can always do that yourself by wrapping your type inside an UnsafeCell.

The standard library CursorMut can provide get_mut because it doesn't expose the links in the returned reference. This would be unsound in this crate because mutable access allows you to unsafely modify the links while the cursor is still iterating it.