Re: [PATCH 2/5] rust: types: introduce `ForeignOwnable`

From: Wedson Almeida Filho
Date: Mon Jan 30 2023 - 00:59:46 EST


On Fri, 27 Jan 2023 at 10:55, Gary Guo <gary@xxxxxxxxxxx> wrote:
>
> On Thu, 19 Jan 2023 14:40:33 -0300
> Wedson Almeida Filho <wedsonaf@xxxxxxxxx> wrote:
>
> > It was originally called `PointerWrapper`. It is used to convert
> > a Rust object to a pointer representation (void *) that can be
> > stored on the C side, used, and eventually returned to Rust.
> >
> > Signed-off-by: Wedson Almeida Filho <wedsonaf@xxxxxxxxx>
> > ---
> > rust/kernel/lib.rs | 1 +
> > rust/kernel/types.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 55 insertions(+)
> >
> > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> > index e0b0e953907d..223564f9f0cc 100644
> > --- a/rust/kernel/lib.rs
> > +++ b/rust/kernel/lib.rs
> > @@ -16,6 +16,7 @@
> > #![feature(coerce_unsized)]
> > #![feature(core_ffi_c)]
> > #![feature(dispatch_from_dyn)]
> > +#![feature(generic_associated_types)]
> > #![feature(receiver_trait)]
> > #![feature(unsize)]
> >
> > diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
> > index f0ad4472292d..5475f6163002 100644
> > --- a/rust/kernel/types.rs
> > +++ b/rust/kernel/types.rs
> > @@ -9,6 +9,60 @@ use core::{
> > ops::{Deref, DerefMut},
> > };
> >
> > +/// Used to transfer ownership to and from foreign (non-Rust) languages.
> > +///
> > +/// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and
> > +/// later may be transferred back to Rust by calling [`Self::from_foreign`].
> > +///
> > +/// This trait is meant to be used in cases when Rust objects are stored in C objects and
> > +/// eventually "freed" back to Rust.
> > +pub trait ForeignOwnable {
> > + /// Type of values borrowed between calls to [`ForeignOwnable::into_foreign`] and
> > + /// [`ForeignOwnable::from_foreign`].
> > + type Borrowed<'a>;
> > +
> > + /// Converts a Rust-owned object to a foreign-owned one.
> > + ///
> > + /// The foreign representation is a pointer to void.
> > + fn into_foreign(self) -> *const core::ffi::c_void;
> > +
> > + /// Borrows a foreign-owned object.
> > + ///
> > + /// # Safety
> > + ///
> > + /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
> > + /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
> > + /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow_mut`]
> > + /// for this object must have been dropped.
> > + unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>;
> > +
> > + /// Mutably borrows a foreign-owned object.
> > + ///
> > + /// # Safety
> > + ///
> > + /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
> > + /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
> > + /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and
> > + /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped.
> > + unsafe fn borrow_mut<T: ForeignOwnable>(ptr: *const core::ffi::c_void) -> ScopeGuard<T, fn(T)> {
>
> I feel that this should could its own guard (maybe `PointerGuard`?) to
> be more semantically meaningful than a `ScopeGuard`.

I prefer not to add yet another type just for this internal type. It's
only used in the implementation of abstractions, and is exported only
to make it simpler for users to refer to types indirectly (e.g., `<T
as ForeignOwnable>::Borrowed<'_>`).

>
> > + // SAFETY: The safety requirements ensure that `ptr` came from a previous call to
> > + // `into_foreign`.
> > + ScopeGuard::new_with_data(unsafe { T::from_foreign(ptr) }, |d| {
> > + d.into_foreign();
> > + })
> > + }
> > +
> > + /// Converts a foreign-owned object back to a Rust-owned one.
> > + ///
> > + /// # Safety
> > + ///
> > + /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for
> > + /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet.
> > + /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and
> > + /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped.
> > + unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self;
> > +}
> > +
> > /// Runs a cleanup function/closure when dropped.
> > ///
> > /// The [`ScopeGuard::dismiss`] function prevents the cleanup function from running.
>