public inbox for rust-for-linux@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] rust: use derive(CoercePointee) on rustc >= 1.83.0
@ 2024-12-02 10:09 Xiangfei Ding
  2024-12-03  8:45 ` Alice Ryhl
  0 siblings, 1 reply; 7+ messages in thread
From: Xiangfei Ding @ 2024-12-02 10:09 UTC (permalink / raw)
  To: rust-for-linux; +Cc: aliceryhl, ojeda, dingxiangfei2009, Xiangfei Ding

The kernel crate relies on both *coerce_unsized*
and *dispatch_from_dyn* unstable features.
Alice Ryhl has proposed [1] the introduction of
the unstable macro `SmartPointer` to reduce such
dependence, along with a RFC patch [2].
Since Rust 1.81.0 this macro, later renamed to
`CoercePointee` at Rust 1.83.0, has been fully
implemented with the naming discussion resolved.

This feature is now on track to stabilization
in the language. In order to do so, we shall start
using this macro in the kernel crate to prove the
functionality and utility of the macro as
the justification of its stabilization.

This patch makes this switch in such a way that
the crate remains backward compatible with older
Rust compiler versions, via the flag
*RUST_COERCE_POINTEE*.

A minimal demostration code is added to
the *samples/rust/rust_print_main.rs* module.

Link: https://rust-lang.github.io/rfcs/3621-derive-smart-pointer.html [1]
Link: https://lore.kernel.org/all/20240823-derive-smart-pointer-v1-1-53769cd37239@google.com/ [2]
Signed-off-by: Xiangfei Ding <dingxiangfei2009@gmail.com>
---
 init/Kconfig                    |  3 +++
 rust/kernel/lib.rs              |  7 ++++---
 rust/kernel/list/arc.rs         |  9 ++++++---
 rust/kernel/sync/arc.rs         | 15 +++++++++++----
 samples/rust/rust_print_main.rs | 15 +++++++++++++++
 5 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/init/Kconfig b/init/Kconfig
index a20e6efd3f0f..eb9b7e24e859 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1978,6 +1978,9 @@ config RUST
 
 	  If unsure, say N.
 
+config RUST_COERCE_POINTEE
+	def_bool y if RUSTC_VERSION >= 108300
+
 config RUSTC_VERSION_TEXT
 	string
 	depends on RUST
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 04dbee70d3e6..b665a28d1c12 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -13,11 +13,12 @@
 
 #![no_std]
 #![feature(arbitrary_self_types)]
-#![feature(coerce_unsized)]
-#![feature(dispatch_from_dyn)]
+#![cfg_attr(CONFIG_RUST_COERCE_POINTEE, feature(derive_coerce_pointee))]
+#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(coerce_unsized))]
+#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(dispatch_from_dyn))]
+#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(unsize))]
 #![feature(inline_const)]
 #![feature(lint_reasons)]
-#![feature(unsize)]
 
 // Ensure conditional compilation based on the kernel configuration works;
 // otherwise we may silently break things like initcall handling.
diff --git a/rust/kernel/list/arc.rs b/rust/kernel/list/arc.rs
index 3483d8c232c4..f5b3a446eae2 100644
--- a/rust/kernel/list/arc.rs
+++ b/rust/kernel/list/arc.rs
@@ -7,7 +7,7 @@
 use crate::alloc::{AllocError, Flags};
 use crate::prelude::*;
 use crate::sync::{Arc, ArcBorrow, UniqueArc};
-use core::marker::{PhantomPinned, Unsize};
+use core::marker::PhantomPinned;
 use core::ops::Deref;
 use core::pin::Pin;
 use core::sync::atomic::{AtomicBool, Ordering};
@@ -159,6 +159,7 @@ fn try_new_list_arc(&self) -> bool {
 ///
 /// [`List`]: crate::list::List
 #[repr(transparent)]
+#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
 pub struct ListArc<T, const ID: u64 = 0>
 where
     T: ListArcSafe<ID> + ?Sized,
@@ -443,18 +444,20 @@ fn as_ref(&self) -> &Arc<T> {
 
 // This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the
 // dynamically-sized type (DST) `U`.
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
 impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID>
 where
-    T: ListArcSafe<ID> + Unsize<U> + ?Sized,
+    T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
     U: ListArcSafe<ID> + ?Sized,
 {
 }
 
 // This is to allow `ListArc<U>` to be dispatched on when `ListArc<T>` can be coerced into
 // `ListArc<U>`.
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
 impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID>
 where
-    T: ListArcSafe<ID> + Unsize<U> + ?Sized,
+    T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
     U: ListArcSafe<ID> + ?Sized,
 {
 }
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index fa4509406ee9..bca3d1f1e1b6 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -26,7 +26,7 @@
 use core::{
     alloc::Layout,
     fmt,
-    marker::{PhantomData, Unsize},
+    marker::PhantomData,
     mem::{ManuallyDrop, MaybeUninit},
     ops::{Deref, DerefMut},
     pin::Pin,
@@ -125,6 +125,8 @@
 /// let coerced: Arc<dyn MyTrait> = obj;
 /// # Ok::<(), Error>(())
 /// ```
+#[repr(transparent)]
+#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
 pub struct Arc<T: ?Sized> {
     ptr: NonNull<ArcInner<T>>,
     _p: PhantomData<ArcInner<T>>,
@@ -172,10 +174,12 @@ unsafe fn container_of(ptr: *const T) -> NonNull<ArcInner<T>> {
 
 // This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the
 // dynamically-sized type (DST) `U`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
 
 // This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
 
 // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because
 // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
@@ -471,6 +475,8 @@ fn from(item: Pin<UniqueArc<T>>) -> Self {
 /// obj.as_arc_borrow().use_reference();
 /// # Ok::<(), Error>(())
 /// ```
+#[repr(transparent)]
+#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
 pub struct ArcBorrow<'a, T: ?Sized + 'a> {
     inner: NonNull<ArcInner<T>>,
     _p: PhantomData<&'a ()>,
@@ -478,7 +484,8 @@ pub struct ArcBorrow<'a, T: ?Sized + 'a> {
 
 // This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
 // `ArcBorrow<U>`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
     for ArcBorrow<'_, T>
 {
 }
diff --git a/samples/rust/rust_print_main.rs b/samples/rust/rust_print_main.rs
index aed90a6feecf..87cf5321f492 100644
--- a/samples/rust/rust_print_main.rs
+++ b/samples/rust/rust_print_main.rs
@@ -34,6 +34,21 @@ fn arc_print() -> Result {
     // Uses `dbg` to print, will move `c` (for temporary debugging purposes).
     dbg!(c);
 
+    {
+        use core::fmt::Display;
+        fn arc_dyn_print(arc: &Arc<dyn Display>) {
+            pr_info!("Arc<dyn Display> says {arc}");
+        }
+        // `Arc` can be used to delegate dynamic dispatch and the following is an example.
+        // Both `i32` and `&str` implements `Display`.
+        // This enables us to express a unified behaviour, contract or protocol
+        // on both `i32` and `&str` into a single `Arc` type `Arc<dyn Display>`.
+        let a_i32_display: Arc<dyn Display> = Arc::new(42i32, GFP_KERNEL)?;
+        let a_str_display: Arc<dyn Display> = a.clone();
+        arc_dyn_print(&a_i32_display);
+        arc_dyn_print(&a_str_display);
+    }
+
     // Pretty-prints the debug formatting with lower-case hexadecimal integers.
     pr_info!("{:#x?}", a);
 
-- 
2.47.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] rust: use derive(CoercePointee) on rustc >= 1.83.0
  2024-12-02 10:09 [PATCH] rust: use derive(CoercePointee) on rustc >= 1.83.0 Xiangfei Ding
@ 2024-12-03  8:45 ` Alice Ryhl
  2024-12-03 20:47   ` Xiangfei Ding
  0 siblings, 1 reply; 7+ messages in thread
From: Alice Ryhl @ 2024-12-03  8:45 UTC (permalink / raw)
  To: Xiangfei Ding; +Cc: rust-for-linux, ojeda, dingxiangfei2009

On Mon, Dec 2, 2024 at 11:10 AM Xiangfei Ding
<dingxiangfei2009@gmail.com> wrote:
>
> The kernel crate relies on both *coerce_unsized*
> and *dispatch_from_dyn* unstable features.
> Alice Ryhl has proposed [1] the introduction of
> the unstable macro `SmartPointer` to reduce such
> dependence, along with a RFC patch [2].
> Since Rust 1.81.0 this macro, later renamed to
> `CoercePointee` at Rust 1.83.0, has been fully
> implemented with the naming discussion resolved.
>
> This feature is now on track to stabilization
> in the language. In order to do so, we shall start
> using this macro in the kernel crate to prove the
> functionality and utility of the macro as
> the justification of its stabilization.

Commit messages are normally wrapped at 72 chars, but this seems to
wrap at 50 chars.

> This patch makes this switch in such a way that
> the crate remains backward compatible with older
> Rust compiler versions, via the flag
> *RUST_COERCE_POINTEE*.
>
> A minimal demostration code is added to
> the *samples/rust/rust_print_main.rs* module.
>
> Link: https://rust-lang.github.io/rfcs/3621-derive-smart-pointer.html [1]
> Link: https://lore.kernel.org/all/20240823-derive-smart-pointer-v1-1-53769cd37239@google.com/ [2]
> Signed-off-by: Xiangfei Ding <dingxiangfei2009@gmail.com>

Overall looks good.

There's a mention of derive(SmartPointer) in the file
rust/kernel/alloc.rs. It should probably be updated to say
derive(CoercePointee) instead.

Alice

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Re: [PATCH] rust: use derive(CoercePointee) on rustc >= 1.83.0
  2024-12-03  8:45 ` Alice Ryhl
@ 2024-12-03 20:47   ` Xiangfei Ding
  2024-12-03 20:47     ` [PATCH v2] " Xiangfei Ding
  0 siblings, 1 reply; 7+ messages in thread
From: Xiangfei Ding @ 2024-12-03 20:47 UTC (permalink / raw)
  To: rust-for-linux; +Cc: aliceryhl, ojeda, dingxiangfei2009

Thank you so much for the review!

I misconfigured the ruler and hopefully the wrapping is correct this
time. I have run through the crate again to apply the new name as well.

Here I will attach a fresh patch for RfL eyes.

Cheers,
Xiang


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2] rust: use derive(CoercePointee) on rustc >= 1.83.0
  2024-12-03 20:47   ` Xiangfei Ding
@ 2024-12-03 20:47     ` Xiangfei Ding
  2024-12-05 11:06       ` Fiona Behrens
                         ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Xiangfei Ding @ 2024-12-03 20:47 UTC (permalink / raw)
  To: rust-for-linux; +Cc: aliceryhl, ojeda, dingxiangfei2009, Xiangfei Ding

The kernel crate relies on both *coerce_unsized* and *dispatch_from_dyn*
unstable features.
Alice Ryhl has proposed [1] the introduction of the unstable macro
`SmartPointer` to reduce such dependence, along with a RFC patch [2].
Since Rust 1.81.0 this macro, later renamed to `CoercePointee` at
Rust 1.83.0, has been fully implemented with the naming discussion
resolved.

This feature is now on track to stabilization in the language.
In order to do so, we shall start using this macro in the kernel crate
to prove the functionality and utility of the macro as the justification
of its stabilization.

This patch makes this switch in such a way that the crate remains
backward compatible with older Rust compiler versions,
via the flag *RUST_COERCE_POINTEE*.

A minimal demostration code is added to the
*samples/rust/rust_print_main.rs* module.

Link: https://rust-lang.github.io/rfcs/3621-derive-smart-pointer.html [1]
Link: https://lore.kernel.org/all/20240823-derive-smart-pointer-v1-1-53769cd37239@google.com/ [2]
Signed-off-by: Xiangfei Ding <dingxiangfei2009@gmail.com>
---
Changes in v2:
- Apply the new name to the `kernel` crate
- Reformat the commit message.

 init/Kconfig                    |  3 +++
 rust/kernel/alloc.rs            |  2 +-
 rust/kernel/lib.rs              |  7 ++++---
 rust/kernel/list/arc.rs         |  9 ++++++---
 rust/kernel/sync/arc.rs         | 15 +++++++++++----
 samples/rust/rust_print_main.rs | 15 +++++++++++++++
 6 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/init/Kconfig b/init/Kconfig
index a20e6efd3f0f..eb9b7e24e859 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1978,6 +1978,9 @@ config RUST
 
 	  If unsure, say N.
 
+config RUST_COERCE_POINTEE
+	def_bool y if RUSTC_VERSION >= 108300
+
 config RUSTC_VERSION_TEXT
 	string
 	depends on RUST
diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs
index f2f7f3a53d29..fc9c9c41cd79 100644
--- a/rust/kernel/alloc.rs
+++ b/rust/kernel/alloc.rs
@@ -123,7 +123,7 @@ pub mod flags {
 /// [`Allocator`] is designed to be implemented as a ZST; [`Allocator`] functions do not operate on
 /// an object instance.
 ///
-/// In order to be able to support `#[derive(SmartPointer)]` later on, we need to avoid a design
+/// In order to be able to support `#[derive(CoercePointee)]` later on, we need to avoid a design
 /// that requires an `Allocator` to be instantiated, hence its functions must not contain any kind
 /// of `self` parameter.
 ///
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 04dbee70d3e6..b665a28d1c12 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -13,11 +13,12 @@
 
 #![no_std]
 #![feature(arbitrary_self_types)]
-#![feature(coerce_unsized)]
-#![feature(dispatch_from_dyn)]
+#![cfg_attr(CONFIG_RUST_COERCE_POINTEE, feature(derive_coerce_pointee))]
+#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(coerce_unsized))]
+#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(dispatch_from_dyn))]
+#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(unsize))]
 #![feature(inline_const)]
 #![feature(lint_reasons)]
-#![feature(unsize)]
 
 // Ensure conditional compilation based on the kernel configuration works;
 // otherwise we may silently break things like initcall handling.
diff --git a/rust/kernel/list/arc.rs b/rust/kernel/list/arc.rs
index 3483d8c232c4..f5b3a446eae2 100644
--- a/rust/kernel/list/arc.rs
+++ b/rust/kernel/list/arc.rs
@@ -7,7 +7,7 @@
 use crate::alloc::{AllocError, Flags};
 use crate::prelude::*;
 use crate::sync::{Arc, ArcBorrow, UniqueArc};
-use core::marker::{PhantomPinned, Unsize};
+use core::marker::PhantomPinned;
 use core::ops::Deref;
 use core::pin::Pin;
 use core::sync::atomic::{AtomicBool, Ordering};
@@ -159,6 +159,7 @@ fn try_new_list_arc(&self) -> bool {
 ///
 /// [`List`]: crate::list::List
 #[repr(transparent)]
+#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
 pub struct ListArc<T, const ID: u64 = 0>
 where
     T: ListArcSafe<ID> + ?Sized,
@@ -443,18 +444,20 @@ fn as_ref(&self) -> &Arc<T> {
 
 // This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the
 // dynamically-sized type (DST) `U`.
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
 impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID>
 where
-    T: ListArcSafe<ID> + Unsize<U> + ?Sized,
+    T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
     U: ListArcSafe<ID> + ?Sized,
 {
 }
 
 // This is to allow `ListArc<U>` to be dispatched on when `ListArc<T>` can be coerced into
 // `ListArc<U>`.
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
 impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID>
 where
-    T: ListArcSafe<ID> + Unsize<U> + ?Sized,
+    T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
     U: ListArcSafe<ID> + ?Sized,
 {
 }
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index fa4509406ee9..bca3d1f1e1b6 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -26,7 +26,7 @@
 use core::{
     alloc::Layout,
     fmt,
-    marker::{PhantomData, Unsize},
+    marker::PhantomData,
     mem::{ManuallyDrop, MaybeUninit},
     ops::{Deref, DerefMut},
     pin::Pin,
@@ -125,6 +125,8 @@
 /// let coerced: Arc<dyn MyTrait> = obj;
 /// # Ok::<(), Error>(())
 /// ```
+#[repr(transparent)]
+#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
 pub struct Arc<T: ?Sized> {
     ptr: NonNull<ArcInner<T>>,
     _p: PhantomData<ArcInner<T>>,
@@ -172,10 +174,12 @@ unsafe fn container_of(ptr: *const T) -> NonNull<ArcInner<T>> {
 
 // This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the
 // dynamically-sized type (DST) `U`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
 
 // This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
 
 // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because
 // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
@@ -471,6 +475,8 @@ fn from(item: Pin<UniqueArc<T>>) -> Self {
 /// obj.as_arc_borrow().use_reference();
 /// # Ok::<(), Error>(())
 /// ```
+#[repr(transparent)]
+#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
 pub struct ArcBorrow<'a, T: ?Sized + 'a> {
     inner: NonNull<ArcInner<T>>,
     _p: PhantomData<&'a ()>,
@@ -478,7 +484,8 @@ pub struct ArcBorrow<'a, T: ?Sized + 'a> {
 
 // This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
 // `ArcBorrow<U>`.
-impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
+#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
+impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
     for ArcBorrow<'_, T>
 {
 }
diff --git a/samples/rust/rust_print_main.rs b/samples/rust/rust_print_main.rs
index aed90a6feecf..87cf5321f492 100644
--- a/samples/rust/rust_print_main.rs
+++ b/samples/rust/rust_print_main.rs
@@ -34,6 +34,21 @@ fn arc_print() -> Result {
     // Uses `dbg` to print, will move `c` (for temporary debugging purposes).
     dbg!(c);
 
+    {
+        use core::fmt::Display;
+        fn arc_dyn_print(arc: &Arc<dyn Display>) {
+            pr_info!("Arc<dyn Display> says {arc}");
+        }
+        // `Arc` can be used to delegate dynamic dispatch and the following is an example.
+        // Both `i32` and `&str` implements `Display`.
+        // This enables us to express a unified behaviour, contract or protocol
+        // on both `i32` and `&str` into a single `Arc` type `Arc<dyn Display>`.
+        let a_i32_display: Arc<dyn Display> = Arc::new(42i32, GFP_KERNEL)?;
+        let a_str_display: Arc<dyn Display> = a.clone();
+        arc_dyn_print(&a_i32_display);
+        arc_dyn_print(&a_str_display);
+    }
+
     // Pretty-prints the debug formatting with lower-case hexadecimal integers.
     pr_info!("{:#x?}", a);
 
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] rust: use derive(CoercePointee) on rustc >= 1.83.0
  2024-12-03 20:47     ` [PATCH v2] " Xiangfei Ding
@ 2024-12-05 11:06       ` Fiona Behrens
  2025-01-06 13:38       ` Alice Ryhl
  2025-01-13 14:45       ` Miguel Ojeda
  2 siblings, 0 replies; 7+ messages in thread
From: Fiona Behrens @ 2024-12-05 11:06 UTC (permalink / raw)
  To: Xiangfei Ding; +Cc: rust-for-linux, aliceryhl, ojeda, dingxiangfei2009



On 3 Dec 2024, at 21:47, Xiangfei Ding wrote:

> The kernel crate relies on both *coerce_unsized* and *dispatch_from_dyn*
> unstable features.
> Alice Ryhl has proposed [1] the introduction of the unstable macro
> `SmartPointer` to reduce such dependence, along with a RFC patch [2].
> Since Rust 1.81.0 this macro, later renamed to `CoercePointee` at
> Rust 1.83.0, has been fully implemented with the naming discussion
> resolved.
>
> This feature is now on track to stabilization in the language.
> In order to do so, we shall start using this macro in the kernel crate
> to prove the functionality and utility of the macro as the justification
> of its stabilization.
>
> This patch makes this switch in such a way that the crate remains
> backward compatible with older Rust compiler versions,
> via the flag *RUST_COERCE_POINTEE*.
>
> A minimal demostration code is added to the
> *samples/rust/rust_print_main.rs* module.
>
> Link: https://rust-lang.github.io/rfcs/3621-derive-smart-pointer.html [1]
> Link: https://lore.kernel.org/all/20240823-derive-smart-pointer-v1-1-53769cd37239@google.com/ [2]
> Signed-off-by: Xiangfei Ding <dingxiangfei2009@gmail.com>

Reviewed-by: Fiona Behrens <me@kloenk.dev>

> ---
> Changes in v2:
> - Apply the new name to the `kernel` crate
> - Reformat the commit message.
>
>  init/Kconfig                    |  3 +++
>  rust/kernel/alloc.rs            |  2 +-
>  rust/kernel/lib.rs              |  7 ++++---
>  rust/kernel/list/arc.rs         |  9 ++++++---
>  rust/kernel/sync/arc.rs         | 15 +++++++++++----
>  samples/rust/rust_print_main.rs | 15 +++++++++++++++
>  6 files changed, 40 insertions(+), 11 deletions(-)
>
> diff --git a/init/Kconfig b/init/Kconfig
> index a20e6efd3f0f..eb9b7e24e859 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1978,6 +1978,9 @@ config RUST
>
>  	  If unsure, say N.
>
> +config RUST_COERCE_POINTEE
> +	def_bool y if RUSTC_VERSION >= 108300
> +
>  config RUSTC_VERSION_TEXT
>  	string
>  	depends on RUST
> diff --git a/rust/kernel/alloc.rs b/rust/kernel/alloc.rs
> index f2f7f3a53d29..fc9c9c41cd79 100644
> --- a/rust/kernel/alloc.rs
> +++ b/rust/kernel/alloc.rs
> @@ -123,7 +123,7 @@ pub mod flags {
>  /// [`Allocator`] is designed to be implemented as a ZST; [`Allocator`] functions do not operate on
>  /// an object instance.
>  ///
> -/// In order to be able to support `#[derive(SmartPointer)]` later on, we need to avoid a design
> +/// In order to be able to support `#[derive(CoercePointee)]` later on, we need to avoid a design
>  /// that requires an `Allocator` to be instantiated, hence its functions must not contain any kind
>  /// of `self` parameter.
>  ///
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index 04dbee70d3e6..b665a28d1c12 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -13,11 +13,12 @@
>
>  #![no_std]
>  #![feature(arbitrary_self_types)]
> -#![feature(coerce_unsized)]
> -#![feature(dispatch_from_dyn)]
> +#![cfg_attr(CONFIG_RUST_COERCE_POINTEE, feature(derive_coerce_pointee))]
> +#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(coerce_unsized))]
> +#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(dispatch_from_dyn))]
> +#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(unsize))]
>  #![feature(inline_const)]
>  #![feature(lint_reasons)]
> -#![feature(unsize)]
>
>  // Ensure conditional compilation based on the kernel configuration works;
>  // otherwise we may silently break things like initcall handling.
> diff --git a/rust/kernel/list/arc.rs b/rust/kernel/list/arc.rs
> index 3483d8c232c4..f5b3a446eae2 100644
> --- a/rust/kernel/list/arc.rs
> +++ b/rust/kernel/list/arc.rs
> @@ -7,7 +7,7 @@
>  use crate::alloc::{AllocError, Flags};
>  use crate::prelude::*;
>  use crate::sync::{Arc, ArcBorrow, UniqueArc};
> -use core::marker::{PhantomPinned, Unsize};
> +use core::marker::PhantomPinned;
>  use core::ops::Deref;
>  use core::pin::Pin;
>  use core::sync::atomic::{AtomicBool, Ordering};
> @@ -159,6 +159,7 @@ fn try_new_list_arc(&self) -> bool {
>  ///
>  /// [`List`]: crate::list::List
>  #[repr(transparent)]
> +#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
>  pub struct ListArc<T, const ID: u64 = 0>
>  where
>      T: ListArcSafe<ID> + ?Sized,
> @@ -443,18 +444,20 @@ fn as_ref(&self) -> &Arc<T> {
>
>  // This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the
>  // dynamically-sized type (DST) `U`.
> +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
>  impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID>
>  where
> -    T: ListArcSafe<ID> + Unsize<U> + ?Sized,
> +    T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
>      U: ListArcSafe<ID> + ?Sized,
>  {
>  }
>
>  // This is to allow `ListArc<U>` to be dispatched on when `ListArc<T>` can be coerced into
>  // `ListArc<U>`.
> +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
>  impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID>
>  where
> -    T: ListArcSafe<ID> + Unsize<U> + ?Sized,
> +    T: ListArcSafe<ID> + core::marker::Unsize<U> + ?Sized,
>      U: ListArcSafe<ID> + ?Sized,
>  {
>  }
> diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
> index fa4509406ee9..bca3d1f1e1b6 100644
> --- a/rust/kernel/sync/arc.rs
> +++ b/rust/kernel/sync/arc.rs
> @@ -26,7 +26,7 @@
>  use core::{
>      alloc::Layout,
>      fmt,
> -    marker::{PhantomData, Unsize},
> +    marker::PhantomData,
>      mem::{ManuallyDrop, MaybeUninit},
>      ops::{Deref, DerefMut},
>      pin::Pin,
> @@ -125,6 +125,8 @@
>  /// let coerced: Arc<dyn MyTrait> = obj;
>  /// # Ok::<(), Error>(())
>  /// ```
> +#[repr(transparent)]
> +#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
>  pub struct Arc<T: ?Sized> {
>      ptr: NonNull<ArcInner<T>>,
>      _p: PhantomData<ArcInner<T>>,
> @@ -172,10 +174,12 @@ unsafe fn container_of(ptr: *const T) -> NonNull<ArcInner<T>> {
>
>  // This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the
>  // dynamically-sized type (DST) `U`.
> -impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
> +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
> +impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
>
>  // This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`.
> -impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
> +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
> +impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
>
>  // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because
>  // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
> @@ -471,6 +475,8 @@ fn from(item: Pin<UniqueArc<T>>) -> Self {
>  /// obj.as_arc_borrow().use_reference();
>  /// # Ok::<(), Error>(())
>  /// ```
> +#[repr(transparent)]
> +#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))]
>  pub struct ArcBorrow<'a, T: ?Sized + 'a> {
>      inner: NonNull<ArcInner<T>>,
>      _p: PhantomData<&'a ()>,
> @@ -478,7 +484,8 @@ pub struct ArcBorrow<'a, T: ?Sized + 'a> {
>
>  // This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
>  // `ArcBorrow<U>`.
> -impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
> +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
> +impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
>      for ArcBorrow<'_, T>
>  {
>  }
> diff --git a/samples/rust/rust_print_main.rs b/samples/rust/rust_print_main.rs
> index aed90a6feecf..87cf5321f492 100644
> --- a/samples/rust/rust_print_main.rs
> +++ b/samples/rust/rust_print_main.rs
> @@ -34,6 +34,21 @@ fn arc_print() -> Result {
>      // Uses `dbg` to print, will move `c` (for temporary debugging purposes).
>      dbg!(c);
>
> +    {
> +        use core::fmt::Display;
> +        fn arc_dyn_print(arc: &Arc<dyn Display>) {
> +            pr_info!("Arc<dyn Display> says {arc}");
> +        }
> +        // `Arc` can be used to delegate dynamic dispatch and the following is an example.
> +        // Both `i32` and `&str` implements `Display`.
> +        // This enables us to express a unified behaviour, contract or protocol
> +        // on both `i32` and `&str` into a single `Arc` type `Arc<dyn Display>`.
> +        let a_i32_display: Arc<dyn Display> = Arc::new(42i32, GFP_KERNEL)?;
> +        let a_str_display: Arc<dyn Display> = a.clone();
> +        arc_dyn_print(&a_i32_display);
> +        arc_dyn_print(&a_str_display);
> +    }
> +
>      // Pretty-prints the debug formatting with lower-case hexadecimal integers.
>      pr_info!("{:#x?}", a);
>
> -- 
> 2.47.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] rust: use derive(CoercePointee) on rustc >= 1.83.0
  2024-12-03 20:47     ` [PATCH v2] " Xiangfei Ding
  2024-12-05 11:06       ` Fiona Behrens
@ 2025-01-06 13:38       ` Alice Ryhl
  2025-01-13 14:45       ` Miguel Ojeda
  2 siblings, 0 replies; 7+ messages in thread
From: Alice Ryhl @ 2025-01-06 13:38 UTC (permalink / raw)
  To: Xiangfei Ding; +Cc: rust-for-linux, ojeda, dingxiangfei2009

On Tue, Dec 3, 2024 at 9:51 PM Xiangfei Ding <dingxiangfei2009@gmail.com> wrote:
>
> The kernel crate relies on both *coerce_unsized* and *dispatch_from_dyn*
> unstable features.
> Alice Ryhl has proposed [1] the introduction of the unstable macro
> `SmartPointer` to reduce such dependence, along with a RFC patch [2].
> Since Rust 1.81.0 this macro, later renamed to `CoercePointee` at
> Rust 1.83.0, has been fully implemented with the naming discussion
> resolved.
>
> This feature is now on track to stabilization in the language.
> In order to do so, we shall start using this macro in the kernel crate
> to prove the functionality and utility of the macro as the justification
> of its stabilization.
>
> This patch makes this switch in such a way that the crate remains
> backward compatible with older Rust compiler versions,
> via the flag *RUST_COERCE_POINTEE*.
>
> A minimal demostration code is added to the
> *samples/rust/rust_print_main.rs* module.
>
> Link: https://rust-lang.github.io/rfcs/3621-derive-smart-pointer.html [1]
> Link: https://lore.kernel.org/all/20240823-derive-smart-pointer-v1-1-53769cd37239@google.com/ [2]
> Signed-off-by: Xiangfei Ding <dingxiangfei2009@gmail.com>\

Reviewed-by: Alice Ryhl <aliceryhl@google.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] rust: use derive(CoercePointee) on rustc >= 1.83.0
  2024-12-03 20:47     ` [PATCH v2] " Xiangfei Ding
  2024-12-05 11:06       ` Fiona Behrens
  2025-01-06 13:38       ` Alice Ryhl
@ 2025-01-13 14:45       ` Miguel Ojeda
  2 siblings, 0 replies; 7+ messages in thread
From: Miguel Ojeda @ 2025-01-13 14:45 UTC (permalink / raw)
  To: Xiangfei Ding; +Cc: rust-for-linux, aliceryhl, ojeda, dingxiangfei2009

On Tue, Dec 3, 2024 at 9:51 PM Xiangfei Ding <dingxiangfei2009@gmail.com> wrote:
>
> This patch makes this switch in such a way that the crate remains
> backward compatible with older Rust compiler versions,
> via the flag *RUST_COERCE_POINTEE*.

Applied to `rust-next` -- thanks everyone!

    [ Fixed version to 1.84. Renamed option to `RUSTC_HAS_COERCE_POINTEE`
      to match `CC_HAS_*` ones. Moved up new config option, closer to the
      `CC_HAS_*` ones. Simplified Kconfig line. Fixed typos and slightly
      reworded example and commit. Added Link to PR. - Miguel ]

Xiangfei: it was in the end 1.84.0, not 1.83.0, right? i.e. commit
fd36b3a4a8168 in upstream Rust (PR:
https://github.com/rust-lang/rust/pull/131284). I tested it and we
would get an error otherwise.

And, of course, please let me know if I made a huge mistake or if you
disagree with any of the changes above -- thanks!

(By the way, I thought about whether we could just use the version in
the Kconfig name, since it could potentially allow to reuse it for
other things. But I doubt we actually reuse much or at all, plus it
looks better with the feature name, plus ideally we will live in a
world where GCC Rust can build the kernel too, and thus we will want
to use actual features for things like this. So I kept the name you
proposed, with the tweak to make it more consistent to the CC ones.)

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-01-13 14:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-02 10:09 [PATCH] rust: use derive(CoercePointee) on rustc >= 1.83.0 Xiangfei Ding
2024-12-03  8:45 ` Alice Ryhl
2024-12-03 20:47   ` Xiangfei Ding
2024-12-03 20:47     ` [PATCH v2] " Xiangfei Ding
2024-12-05 11:06       ` Fiona Behrens
2025-01-06 13:38       ` Alice Ryhl
2025-01-13 14:45       ` Miguel Ojeda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox