public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@gmail.com>
To: Alice Ryhl <aliceryhl@google.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Trevor Gross" <tmgross@umich.edu>,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 2/2] rust: list: make the cursor point between elements
Date: Tue, 21 Jan 2025 13:15:13 -0800	[thread overview]
Message-ID: <Z5AOYbZGhgB19KzC@tardis.local> (raw)
In-Reply-To: <20250121-cursor-between-v2-2-1b24cd377618@google.com>

On Tue, Jan 21, 2025 at 10:14:24AM +0000, Alice Ryhl wrote:
[...]
> +/// References the element in the list next to the cursor.
> +///
> +/// # Invariants
> +///
> +/// * `ptr` is an element in `self.cursor.list`.
> +/// * `ISNEXT == (self.ptr == self.cursor.next)`.
> +pub struct CursorPeek<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64> {
> +    cursor: &'a mut Cursor<'b, T, ID>,
> +    ptr: *mut ListLinksFields,
> +}
> +
> +impl<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64>
> +    CursorPeek<'a, 'b, T, ISNEXT, ID>
> +{
> +    /// Remove the element from the list.
>      pub fn remove(self) -> ListArc<T, ID> {
> -        // SAFETY: The `current` pointer always points at a member of the list.
> -        unsafe { self.list.remove_internal(self.current) }
> +        if ISNEXT {
> +            self.cursor.move_next();
> +        }
> +
> +        // INVARIANT: `self.ptr` is not equal to `self.cursor.next` due to the above `move_next`
> +        // call.
> +        // SAFETY: By the type invariants of `Self`, `next` is not null, so `next` is an element of
> +        // `self.cursor.list` by the type invariants of `Cursor`.
> +        unsafe { self.cursor.list.remove_internal(self.ptr) }
> +    }
> +
> +    /// Access this value as an [`ArcBorrow`].
> +    pub fn arc(&self) -> ArcBorrow<'_, T> {
> +        // SAFETY: `self.ptr` points at an element in `self.cursor.list`.
> +        let me = unsafe { T::view_value(ListLinks::from_fields(self.ptr)) };
> +        // SAFETY:
> +        // * All values in a list are stored in an `Arc`.
> +        // * The value cannot be removed from the list for the duration of the lifetime annotated
> +        //   on the returned `ArcBorrow`, because removing it from the list would require mutable
> +        //   access to the `CursorPeek`, the `Cursor` or the `List`. However, the `ArcBorrow` holds
> +        //   an immutable borrow on the `CursorPeek`, which in turn holds a mutable borrow on the
> +        //   `Cursor`, which in turn holds a mutable borrow on the `List`, so any such mutable
> +        //   access requires first releasing the immutable borrow on the `CursorPeek`.
> +        // * Values in a list never have a `UniqueArc` reference, because the list has a `ListArc`
> +        //   reference, and `UniqueArc` references must be unique.
> +        unsafe { ArcBorrow::from_raw(me) }
> +    }
> +}
> +
> +impl<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64> core::ops::Deref
> +    for CursorPeek<'a, 'b, T, ISNEXT, ID>
> +{
> +    // This can't use `ArcBorrow<'a, T>` as the target type because 'a is too long. It would let
> +    // you obtain an `ArcBorrow<'a, T>` and then call `CursorPeek::remove` without giving up the
> +    // `ArcBorrow<'a, T>`.

I'm not sure whether we want to mention `ArcBorrow<'a, T>` here, because
`ArcBorrow<'a, T>` is a (smart) pointer type, which should never be used
as a `Deref::Target`, otherwise CursorPeek::deref() would return a
&ArcBorrow<'a, T>, which doesn't make sense, and a bit challenging to
implement I think?

> +    type Target = T;
> +
> +    fn deref(&self) -> &T {
> +        // SAFETY: `self.ptr` points at an element in `self.cursor.list`.
> +        let me = unsafe { T::view_value(ListLinks::from_fields(self.cursor.next)) };

Shouldn't this be `self.ptr` instead of `self.cursor.next`?

Regards,
Boqun

> +
> +        // SAFETY: The value cannot be removed from the list for the duration of the lifetime
> +        // annotated on the returned `&T`, because removing it from the list would require mutable
> +        // access to the `CursorPeek`, the `Cursor` or the `List`. However, the `&T` holds an
> +        // immutable borrow on the `CursorPeek`, which in turn holds a mutable borrow on the
> +        // `Cursor`, which in turn holds a mutable borrow on the `List`, so any such mutable access
> +        // requires first releasing the immutable borrow on the `CursorPeek`.
> +        unsafe { &*me }
>      }
>  }
>  
> 
> -- 
> 2.48.0.rc2.279.g1de40edade-goog
> 

  parent reply	other threads:[~2025-01-21 21:15 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-21 10:14 [PATCH v2 0/2] Make the Rust linked list cursor point between elements Alice Ryhl
2025-01-21 10:14 ` [PATCH v2 1/2] rust: list: extract common code for insertion Alice Ryhl
2025-01-21 13:04   ` Andreas Hindborg
2025-01-21 10:14 ` [PATCH v2 2/2] rust: list: make the cursor point between elements Alice Ryhl
2025-01-21 13:06   ` Andreas Hindborg
2025-01-21 21:15   ` Boqun Feng [this message]
2025-01-22 10:02     ` Alice Ryhl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Z5AOYbZGhgB19KzC@tardis.local \
    --to=boqun.feng@gmail.com \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox