From: Xiangfei Ding <dingxiangfei2009@gmail.com>
To: rust-for-linux@vger.kernel.org
Cc: aliceryhl@google.com, ojeda@kernel.org,
dingxiangfei2009@protonmail.ch,
Xiangfei Ding <dingxiangfei2009@gmail.com>
Subject: [PATCH v2] rust: use derive(CoercePointee) on rustc >= 1.83.0
Date: Wed, 4 Dec 2024 04:47:49 +0800 [thread overview]
Message-ID: <20241203205050.679106-2-dingxiangfei2009@gmail.com> (raw)
In-Reply-To: <20241203205050.679106-1-dingxiangfei2009@gmail.com>
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
next prev parent reply other threads:[~2024-12-03 20:51 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Xiangfei Ding [this message]
2024-12-05 11:06 ` [PATCH v2] " Fiona Behrens
2025-01-06 13:38 ` Alice Ryhl
2025-01-13 14:45 ` Miguel Ojeda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241203205050.679106-2-dingxiangfei2009@gmail.com \
--to=dingxiangfei2009@gmail.com \
--cc=aliceryhl@google.com \
--cc=dingxiangfei2009@protonmail.ch \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox