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

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