Skip to content

Commit

Permalink
switch to CoercePointee macro, with examples
Browse files Browse the repository at this point in the history
  • Loading branch information
dingxiangfei2009 committed Nov 20, 2024
1 parent ae7851c commit 54c00aa
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 35 deletions.
2 changes: 1 addition & 1 deletion rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#![no_std]
#![feature(arbitrary_self_types)]
#![feature(coerce_unsized)]
#![feature(dispatch_from_dyn)]
#![feature(derive_coerce_pointee, pin_coerce_unsized_trait)]
#![feature(inline_const)]
#![feature(lint_reasons)]
#![feature(unsize)]
Expand Down
25 changes: 6 additions & 19 deletions rust/kernel/list/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
use crate::alloc::{AllocError, Flags};
use crate::prelude::*;
use crate::sync::{Arc, ArcBorrow, UniqueArc};
use core::marker::{PhantomPinned, Unsize};
use core::marker::CoercePointee;
use core::marker::PhantomPinned;
use core::ops::Deref;
use core::pin::Pin;
use core::pin::{Pin, PinCoerceUnsized};
use core::sync::atomic::{AtomicBool, Ordering};

/// Declares that this type has some way to ensure that there is exactly one `ListArc` instance for
Expand Down Expand Up @@ -159,6 +160,7 @@ pub use impl_list_arc_safe;
///
/// [`List`]: crate::list::List
#[repr(transparent)]
#[derive(CoercePointee)]
pub struct ListArc<T, const ID: u64 = 0>
where
T: ListArcSafe<ID> + ?Sized,
Expand Down Expand Up @@ -441,23 +443,8 @@ where
}
}

// This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the
// dynamically-sized type (DST) `U`.
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>`.
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.
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
20 changes: 5 additions & 15 deletions rust/kernel/sync/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
use core::{
alloc::Layout,
fmt,
marker::{PhantomData, Unsize},
marker::{CoercePointee, PhantomData},
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
pin::Pin,
Expand Down Expand Up @@ -125,6 +125,8 @@ mod std_vendor;
/// let coerced: Arc<dyn MyTrait> = obj;
/// # Ok::<(), Error>(())
/// ```
#[repr(transparent)]
#[derive(CoercePointee)]
pub struct Arc<T: ?Sized> {
ptr: NonNull<ArcInner<T>>,
_p: PhantomData<ArcInner<T>>,
Expand Down Expand Up @@ -170,13 +172,6 @@ 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`.
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>`.
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 @@ -471,18 +466,13 @@ impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {
/// obj.as_arc_borrow().use_reference();
/// # Ok::<(), Error>(())
/// ```
#[repr(transparent)]
#[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>`.
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
13 changes: 13 additions & 0 deletions samples/rust/rust_print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,25 @@ 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);

// 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 54c00aa

Please sign in to comment.