Skip to content

Commit

Permalink
gating behind version 1.83.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dingxiangfei2009 committed Nov 22, 2024
1 parent 54c00aa commit 27e8103
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 21 deletions.
3 changes: 3 additions & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1964,6 +1964,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
Expand Down
8 changes: 5 additions & 3 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
#![no_std]
#![feature(arbitrary_self_types)]
#![feature(coerce_unsized)]
#![feature(derive_coerce_pointee, pin_coerce_unsized_trait)]
#![cfg_attr(
CONFIG_RUST_COERCE_POINTEE,
feature(derive_coerce_pointee, pin_coerce_unsized_trait)
)]
#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(coerce_unsized, 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.
Expand Down
23 changes: 22 additions & 1 deletion rust/kernel/list/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub use impl_list_arc_safe;
///
/// [`List`]: crate::list::List
#[repr(transparent)]
#[derive(CoercePointee)]
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(CoercePointee))]
pub struct ListArc<T, const ID: u64 = 0>
where
T: ListArcSafe<ID> + ?Sized,
Expand Down Expand Up @@ -443,7 +443,28 @@ where
}
}

// 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,
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,
U: ListArcSafe<ID> + ?Sized,
{
}

/// `ListArc` is well-behaved so that its dereferencing operation does not mutate.
#[cfg(CONFIG_RUST_COERCE_POINTEE)]
unsafe impl<T: ?Sized + ListArcSafe<ID>, const ID: u64> PinCoerceUnsized for ListArc<T, ID> {}

/// A utility for tracking whether a [`ListArc`] exists using an atomic.
Expand Down
31 changes: 26 additions & 5 deletions rust/kernel/sync/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ use crate::{
try_init,
types::{ForeignOwnable, Opaque},
};
#[cfg(CONFIG_RUST_COERCE_POINTEE)]
use core::marker::CoercePointee;
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
use core::marker::Unsize;
use core::{
alloc::Layout,
fmt,
marker::{CoercePointee, PhantomData},
marker::PhantomData,
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
pin::Pin,
Expand Down Expand Up @@ -125,8 +129,8 @@ mod std_vendor;
/// let coerced: Arc<dyn MyTrait> = obj;
/// # Ok::<(), Error>(())
/// ```
#[repr(transparent)]
#[derive(CoercePointee)]
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, repr(transparent))]
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(CoercePointee))]
pub struct Arc<T: ?Sized> {
ptr: NonNull<ArcInner<T>>,
_p: PhantomData<ArcInner<T>>,
Expand Down Expand Up @@ -172,6 +176,15 @@ impl<T: ?Sized> 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`.
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
impl<T: ?Sized + 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>`.
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
impl<T: ?Sized + 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
// `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` using a
Expand Down Expand Up @@ -466,13 +479,21 @@ impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {
/// obj.as_arc_borrow().use_reference();
/// # Ok::<(), Error>(())
/// ```
#[repr(transparent)]
#[derive(CoercePointee)]
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, repr(transparent))]
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(CoercePointee))]
pub struct ArcBorrow<'a, T: ?Sized + 'a> {
inner: NonNull<ArcInner<T>>,
_p: PhantomData<&'a ()>,
}

// This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
// `ArcBorrow<U>`.
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
for ArcBorrow<'_, T>
{
}

impl<T: ?Sized> Clone for ArcBorrow<'_, T> {
fn clone(&self) -> Self {
*self
Expand Down
33 changes: 21 additions & 12 deletions samples/rust/rust_print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,34 @@ fn arc_print() -> Result {
// Uses `dbg` to print, will move `c` (for temporary debugging purposes).
dbg!(c);

// `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`
// in 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);
#[cfg(CONFIG_RUST_COERCE_POINTEE)]
{
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`
// in 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);
}

#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
pr_info!(
"The demonstration for dynamic dispatching through Arc is skipped. "
"To see the print-out from this example, please upgrade your Rust compiler to 1.83.0 or higher.\n"
);

// Pretty-prints the debug formatting with lower-case hexadecimal integers.
pr_info!("{:#x?}", a);

Ok(())
}

fn arc_dyn_print(arc: &Arc<dyn Display>) {
pr_info!("Arc<dyn Display> says {arc}");
}

impl kernel::Module for RustPrint {
fn init(_module: &'static ThisModule) -> Result<Self> {
pr_info!("Rust printing macros sample (init)\n");
Expand Down

0 comments on commit 27e8103

Please sign in to comment.