diff --git a/init/Kconfig b/init/Kconfig index a20e6efd3f0fbd..eb9b7e24e859b0 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 04dbee70d3e66a..b665a28d1c123a 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 3483d8c232c4f1..f5b3a446eae25c 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 @@ pub use impl_list_arc_safe; /// /// [`List`]: crate::list::List #[repr(transparent)] +#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))] pub struct ListArc where T: ListArcSafe + ?Sized, @@ -443,18 +444,20 @@ where // This is to allow coercion from `ListArc` to `ListArc` if `T` can be converted to the // dynamically-sized type (DST) `U`. +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))] impl core::ops::CoerceUnsized> for ListArc where - T: ListArcSafe + Unsize + ?Sized, + T: ListArcSafe + core::marker::Unsize + ?Sized, U: ListArcSafe + ?Sized, { } // This is to allow `ListArc` to be dispatched on when `ListArc` can be coerced into // `ListArc`. +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))] impl core::ops::DispatchFromDyn> for ListArc where - T: ListArcSafe + Unsize + ?Sized, + T: ListArcSafe + core::marker::Unsize + ?Sized, U: ListArcSafe + ?Sized, { } diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index fa4509406ee909..bca3d1f1e1b6f8 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -26,7 +26,7 @@ use crate::{ use core::{ alloc::Layout, fmt, - marker::{PhantomData, Unsize}, + marker::PhantomData, mem::{ManuallyDrop, MaybeUninit}, ops::{Deref, DerefMut}, pin::Pin, @@ -125,6 +125,8 @@ mod std_vendor; /// let coerced: Arc = obj; /// # Ok::<(), Error>(()) /// ``` +#[repr(transparent)] +#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(core::marker::CoercePointee))] pub struct Arc { ptr: NonNull>, _p: PhantomData>, @@ -172,10 +174,12 @@ impl ArcInner { // This is to allow coercion from `Arc` to `Arc` if `T` can be converted to the // dynamically-sized type (DST) `U`. -impl, U: ?Sized> core::ops::CoerceUnsized> for Arc {} +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))] +impl, U: ?Sized> core::ops::CoerceUnsized> for Arc {} // This is to allow `Arc` to be dispatched on when `Arc` can be coerced into `Arc`. -impl, U: ?Sized> core::ops::DispatchFromDyn> for Arc {} +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))] +impl, U: ?Sized> core::ops::DispatchFromDyn> for Arc {} // SAFETY: It is safe to send `Arc` 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 @@ impl From>> for Arc { /// 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>, _p: PhantomData<&'a ()>, @@ -478,7 +484,8 @@ pub struct ArcBorrow<'a, T: ?Sized + 'a> { // This is to allow `ArcBorrow` to be dispatched on when `ArcBorrow` can be coerced into // `ArcBorrow`. -impl, U: ?Sized> core::ops::DispatchFromDyn> +#[cfg(not(CONFIG_RUST_COERCE_POINTEE))] +impl, U: ?Sized> core::ops::DispatchFromDyn> for ArcBorrow<'_, T> { } diff --git a/samples/rust/rust_print_main.rs b/samples/rust/rust_print_main.rs index aed90a6feecfa7..87cf5321f49254 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) { + pr_info!("Arc 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`. + let a_i32_display: Arc = Arc::new(42i32, GFP_KERNEL)?; + let a_str_display: Arc = 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);