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

Message ID 20230119174036.64046-2-wedsonaf@gmail.com
State New
Headers
Series [1/5] rust: types: introduce `ScopeGuard` |

Commit Message

Wedson Almeida Filho Jan. 19, 2023, 5:40 p.m. UTC
  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@gmail.com>
---
 rust/kernel/lib.rs   |  1 +
 rust/kernel/types.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)
  

Comments

Boqun Feng Jan. 20, 2023, 7:59 p.m. UTC | #1
On Thu, Jan 19, 2023 at 02:40:33PM -0300, Wedson Almeida Filho 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@gmail.com>
> ---
>  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)> {
> +        // 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();
> +        })

I kinda want to suggest borrow_mut() to be implemented as:

    pub trait ForeignOwnable {
        ...
        unsafe fn borrow_mut(ptr: *const core::ffi::c_void) -> ScopeGuard<Self, fn(Self)> {
            // SAFETY: The safety requirements ensure that `ptr` came from a previous call to
            // `into_foreign`.
            ScopeGuard::new_with_data(unsafe { Self::from_foreign(ptr) }, |d| {
                d.into_foreign();
            })
    }

to avoid funny code as follow:

	let a = Box::new(0).into_foreign();
	// Using an irrelevant `impl ForeignOwnable` to `borrow_mut`
	let borrowed_a: ScopeGuard<Box<i32>, ...> = unsafe { Arc::<u64>::borrow_mut(a) };

but that requires `Self: Sized`. Is it too restrictive?

Regards,
Boqun

> +    }
> +
> +    /// 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.
> -- 
> 2.34.1
>
  
Wedson Almeida Filho Jan. 22, 2023, 6:34 a.m. UTC | #2
On Fri, 20 Jan 2023 at 16:59, Boqun Feng <boqun.feng@gmail.com> wrote:
>
> On Thu, Jan 19, 2023 at 02:40:33PM -0300, Wedson Almeida Filho 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@gmail.com>
> > ---
> >  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)> {
> > +        // 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();
> > +        })
>
> I kinda want to suggest borrow_mut() to be implemented as:
>
>     pub trait ForeignOwnable {
>         ...
>         unsafe fn borrow_mut(ptr: *const core::ffi::c_void) -> ScopeGuard<Self, fn(Self)> {
>             // SAFETY: The safety requirements ensure that `ptr` came from a previous call to
>             // `into_foreign`.
>             ScopeGuard::new_with_data(unsafe { Self::from_foreign(ptr) }, |d| {
>                 d.into_foreign();
>             })
>     }

Oh, eliminate the generic type `T` and just use `Self`. Yes, I think
that's a good simplification.

>
> to avoid funny code as follow:
>
>         let a = Box::new(0).into_foreign();
>         // Using an irrelevant `impl ForeignOwnable` to `borrow_mut`
>         let borrowed_a: ScopeGuard<Box<i32>, ...> = unsafe { Arc::<u64>::borrow_mut(a) };
>
> but that requires `Self: Sized`. Is it too restrictive?

It isn't. Since we want the raw pointer to fit in a single pointer
(from C's perspective), we already require `Self: Sized`.

I'll make this change in v2.

>
> Regards,
> Boqun
>
> > +    }
> > +
> > +    /// 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.
> > --
> > 2.34.1
> >
  
Gary Guo Jan. 27, 2023, 1:55 p.m. UTC | #3
On Thu, 19 Jan 2023 14:40:33 -0300
Wedson Almeida Filho <wedsonaf@gmail.com> 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@gmail.com>
> ---
>  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`.

> +        // 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.
  
Vincenzo Palazzo Jan. 28, 2023, 10:42 a.m. UTC | #4
On Thu Jan 19, 2023 at 6:40 PM CET, Wedson Almeida Filho 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@gmail.com>
Reviewed-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>

> ---
>  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)> {
> +        // 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.
> -- 
> 2.34.1
  
Martin Rodriguez Reboredo Jan. 28, 2023, 2:53 p.m. UTC | #5
On Thu, Jan 19, 2023 at 02:40:33PM -0300, Wedson Almeida Filho 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@gmail.com>
> ---
>  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>;

Is it there a possibility that this could make use of borrowing features
like AsRef/Borrowed/Deref?

> +
> +    /// 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)> {
> +        // 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();
> +        })
> +    }

Could these three methods have a borrowing equivalent? When I was
working on some features for the USB module I've stumbled upon the case
of having to encode a pointer (with a pivot) and I cannot do it without
taking ownership of the pointer.

> +
> +    /// 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.
> -- 
> 2.34.1

Aside from these comments I observe that there's a possibility to make
ForeignOwnable a const trait and have non const implementors. Otherwise
if these things are out of scope, no problem whatsoever and this has my
OK.

Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
  
Boqun Feng Jan. 28, 2023, 5:05 p.m. UTC | #6
On Sat, Jan 28, 2023 at 11:53:45AM -0300, Martin Rodriguez Reboredo wrote:
[...]
> > +    /// 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)> {
> > +        // 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();
> > +        })
> > +    }
> 
> Could these three methods have a borrowing equivalent? When I was
> working on some features for the USB module I've stumbled upon the case
> of having to encode a pointer (with a pivot) and I cannot do it without
> taking ownership of the pointer.
> 

*const T is Copy, so you can still use it after pass it to a function or
a new binding, e.g.

	pub fn use_ptr(ptr: *const i32) { .. }

	let p: *const i32 = some_func();

	let q = p;

	// q is just a copy of p
	use_ptr(p);
	// passing to a function parameter is just copying
	use_ptr(p);

maybe I'm missing something subtle, but if you have an example I can
help take a look.

Regards,
Boqun

> > +
> > +    /// 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.
> > -- 
> > 2.34.1
> 
> Aside from these comments I observe that there's a possibility to make
> ForeignOwnable a const trait and have non const implementors. Otherwise
> if these things are out of scope, no problem whatsoever and this has my
> OK.
> 
> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
  
Martin Rodriguez Reboredo Jan. 28, 2023, 8:46 p.m. UTC | #7
On 1/28/23 14:05, Boqun Feng wrote:
> On Sat, Jan 28, 2023 at 11:53:45AM -0300, Martin Rodriguez Reboredo wrote:
> [...]
>>> +    /// 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)> {
>>> +        // 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();
>>> +        })
>>> +    }
>>
>> Could these three methods have a borrowing equivalent? When I was
>> working on some features for the USB module I've stumbled upon the case
>> of having to encode a pointer (with a pivot) and I cannot do it without
>> taking ownership of the pointer.
>>
> 
> *const T is Copy, so you can still use it after pass it to a function or
> a new binding, e.g.
> 
> 	pub fn use_ptr(ptr: *const i32) { .. }
> 
> 	let p: *const i32 = some_func();
> 
> 	let q = p;
> 
> 	// q is just a copy of p
> 	use_ptr(p);
> 	// passing to a function parameter is just copying
> 	use_ptr(p);
> 
> maybe I'm missing something subtle, but if you have an example I can
> help take a look.
> 
> Regards,
> Boqun
> 

I'll use a much more simple example. If I want to take the byte offset
between two `ForeignWrapper`s I'd have to take ownership of them, but I
don't see it desirable in some cases.

    fn byte_offset<P: PointerWrapper>(ptr: P, pivot: P) -> isize {
        unsafe {
            ptr.into_pointer().cast::<u8>()
                .byte_offset(pivot.into_pointer().cast())
        }
    }

But if there was an `as_pointer(&self) -> *const c_void` method then the
above function will be able to borrow both `ForeignWrapper`s.

    fn byte_offset<P: PointerWrapper>(ptr: &P, pivot: &P) -> isize {
        unsafe {
            ptr.as_pointer().cast::<u8>()
                .byte_offset(pivot.as_pointer().cast())
        }
    }

Obviously those methods that borrow will announce invariancies in their
doc comments. If these can exist then great and if not then another
solution could be explored.

>>> +
>>> +    /// 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.
>>> -- 
>>> 2.34.1
>>
>> Aside from these comments I observe that there's a possibility to make
>> ForeignOwnable a const trait and have non const implementors. Otherwise
>> if these things are out of scope, no problem whatsoever and this has my
>> OK.
>>
>> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
  
Boqun Feng Jan. 28, 2023, 10:07 p.m. UTC | #8
On Sat, Jan 28, 2023 at 05:46:50PM -0300, Martin Rodriguez Reboredo wrote:
> On 1/28/23 14:05, Boqun Feng wrote:
> > On Sat, Jan 28, 2023 at 11:53:45AM -0300, Martin Rodriguez Reboredo wrote:
> > [...]
> >>> +    /// 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)> {
> >>> +        // 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();
> >>> +        })
> >>> +    }
> >>
> >> Could these three methods have a borrowing equivalent? When I was
> >> working on some features for the USB module I've stumbled upon the case
> >> of having to encode a pointer (with a pivot) and I cannot do it without
> >> taking ownership of the pointer.
> >>
> > 
> > *const T is Copy, so you can still use it after pass it to a function or
> > a new binding, e.g.
> > 
> > 	pub fn use_ptr(ptr: *const i32) { .. }
> > 
> > 	let p: *const i32 = some_func();
> > 
> > 	let q = p;
> > 
> > 	// q is just a copy of p
> > 	use_ptr(p);
> > 	// passing to a function parameter is just copying
> > 	use_ptr(p);
> > 
> > maybe I'm missing something subtle, but if you have an example I can
> > help take a look.
> > 
> > Regards,
> > Boqun
> > 
> 
> I'll use a much more simple example. If I want to take the byte offset
> between two `ForeignWrapper`s I'd have to take ownership of them, but I
> don't see it desirable in some cases.
> 
>     fn byte_offset<P: PointerWrapper>(ptr: P, pivot: P) -> isize {
>         unsafe {
>             ptr.into_pointer().cast::<u8>()
>                 .byte_offset(pivot.into_pointer().cast())
>         }
>     }
> 
> But if there was an `as_pointer(&self) -> *const c_void` method then the
> above function will be able to borrow both `ForeignWrapper`s.
> 
>     fn byte_offset<P: PointerWrapper>(ptr: &P, pivot: &P) -> isize {
>         unsafe {
>             ptr.as_pointer().cast::<u8>()
>                 .byte_offset(pivot.as_pointer().cast())
>         }
>     }
> 
> Obviously those methods that borrow will announce invariancies in their
> doc comments. If these can exist then great and if not then another
> solution could be explored.
> 

For this particular use case, IIUC, what you need is exactly `AsRef`:

     fn byte_offset<T, P: AsRef<T>>(ptr: &P, pivot: &P) -> isize {
         unsafe {
             (ptr.as_ref() as *const _).cast::<u8>()
                 .byte_offset((pivot.as_ref() *const _).cast())
         }
     }

or you can implement a as_pointer() helper function to avoid the
duplicate `.as_ref() as *const _`:

    fn as_pointer<T, P: AsRef<T>>(ptr: &P) -> *const T {
        ptr.as_ref() as *const T
    }

Although, we need to `impl AsRef<T> for Arc<T>` to make it work for
`Arc<T>`, which is currently missing.

Regards,
Boqun

> >>> +
> >>> +    /// 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.
> >>> -- 
> >>> 2.34.1
> >>
> >> Aside from these comments I observe that there's a possibility to make
> >> ForeignOwnable a const trait and have non const implementors. Otherwise
> >> if these things are out of scope, no problem whatsoever and this has my
> >> OK.
> >>
> >> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
  
Martin Rodriguez Reboredo Jan. 29, 2023, 3:52 a.m. UTC | #9
On 1/28/23 19:07, Boqun Feng wrote:
> On Sat, Jan 28, 2023 at 05:46:50PM -0300, Martin Rodriguez Reboredo wrote:
>> On 1/28/23 14:05, Boqun Feng wrote:
>>> On Sat, Jan 28, 2023 at 11:53:45AM -0300, Martin Rodriguez Reboredo wrote:
>>> [...]
>>>>> +    /// 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)> {
>>>>> +        // 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();
>>>>> +        })
>>>>> +    }
>>>>
>>>> Could these three methods have a borrowing equivalent? When I was
>>>> working on some features for the USB module I've stumbled upon the case
>>>> of having to encode a pointer (with a pivot) and I cannot do it without
>>>> taking ownership of the pointer.
>>>>
>>>
>>> *const T is Copy, so you can still use it after pass it to a function or
>>> a new binding, e.g.
>>>
>>> 	pub fn use_ptr(ptr: *const i32) { .. }
>>>
>>> 	let p: *const i32 = some_func();
>>>
>>> 	let q = p;
>>>
>>> 	// q is just a copy of p
>>> 	use_ptr(p);
>>> 	// passing to a function parameter is just copying
>>> 	use_ptr(p);
>>>
>>> maybe I'm missing something subtle, but if you have an example I can
>>> help take a look.
>>>
>>> Regards,
>>> Boqun
>>>
>>
>> I'll use a much more simple example. If I want to take the byte offset
>> between two `ForeignWrapper`s I'd have to take ownership of them, but I
>> don't see it desirable in some cases.
>>
>>     fn byte_offset<P: PointerWrapper>(ptr: P, pivot: P) -> isize {
>>         unsafe {
>>             ptr.into_pointer().cast::<u8>()
>>                 .byte_offset(pivot.into_pointer().cast())
>>         }
>>     }
>>
>> But if there was an `as_pointer(&self) -> *const c_void` method then the
>> above function will be able to borrow both `ForeignWrapper`s.
>>
>>     fn byte_offset<P: PointerWrapper>(ptr: &P, pivot: &P) -> isize {
>>         unsafe {
>>             ptr.as_pointer().cast::<u8>()
>>                 .byte_offset(pivot.as_pointer().cast())
>>         }
>>     }
>>
>> Obviously those methods that borrow will announce invariancies in their
>> doc comments. If these can exist then great and if not then another
>> solution could be explored.
>>
> 
> For this particular use case, IIUC, what you need is exactly `AsRef`:
> 
>      fn byte_offset<T, P: AsRef<T>>(ptr: &P, pivot: &P) -> isize {
>          unsafe {
>              (ptr.as_ref() as *const _).cast::<u8>()
>                  .byte_offset((pivot.as_ref() *const _).cast())
>          }
>      }
> 
> or you can implement a as_pointer() helper function to avoid the
> duplicate `.as_ref() as *const _`:
> 
>     fn as_pointer<T, P: AsRef<T>>(ptr: &P) -> *const T {
>         ptr.as_ref() as *const T
>     }
> 
> Although, we need to `impl AsRef<T> for Arc<T>` to make it work for
> `Arc<T>`, which is currently missing.
> 
> Regards,
> Boqun
> 

Now that you say it I think that I can do what I wanted by further
constraining it to `ForeignOwnable` plus `AsRef`, so thanks for the tip
Boqun.

>>>>> +
>>>>> +    /// 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.
>>>>> -- 
>>>>> 2.34.1
>>>>
>>>> Aside from these comments I observe that there's a possibility to make
>>>> ForeignOwnable a const trait and have non const implementors. Otherwise
>>>> if these things are out of scope, no problem whatsoever and this has my
>>>> OK.
>>>>
>>>> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
  
Wedson Almeida Filho Jan. 30, 2023, 5:59 a.m. UTC | #10
On Fri, 27 Jan 2023 at 10:55, Gary Guo <gary@garyguo.net> wrote:
>
> On Thu, 19 Jan 2023 14:40:33 -0300
> Wedson Almeida Filho <wedsonaf@gmail.com> 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@gmail.com>
> > ---
> >  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.
>
  

Patch

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)> {
+        // 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.