Skip to content

Commit 54c00aa

Browse files
switch to CoercePointee macro, with examples
1 parent ae7851c commit 54c00aa

File tree

4 files changed

+25
-35
lines changed

4 files changed

+25
-35
lines changed

rust/kernel/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#![no_std]
1515
#![feature(arbitrary_self_types)]
1616
#![feature(coerce_unsized)]
17-
#![feature(dispatch_from_dyn)]
17+
#![feature(derive_coerce_pointee, pin_coerce_unsized_trait)]
1818
#![feature(inline_const)]
1919
#![feature(lint_reasons)]
2020
#![feature(unsize)]

rust/kernel/list/arc.rs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
use crate::alloc::{AllocError, Flags};
88
use crate::prelude::*;
99
use crate::sync::{Arc, ArcBorrow, UniqueArc};
10-
use core::marker::{PhantomPinned, Unsize};
10+
use core::marker::CoercePointee;
11+
use core::marker::PhantomPinned;
1112
use core::ops::Deref;
12-
use core::pin::Pin;
13+
use core::pin::{Pin, PinCoerceUnsized};
1314
use core::sync::atomic::{AtomicBool, Ordering};
1415

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

444-
// This is to allow coercion from `ListArc<T>` to `ListArc<U>` if `T` can be converted to the
445-
// dynamically-sized type (DST) `U`.
446-
impl<T, U, const ID: u64> core::ops::CoerceUnsized<ListArc<U, ID>> for ListArc<T, ID>
447-
where
448-
T: ListArcSafe<ID> + Unsize<U> + ?Sized,
449-
U: ListArcSafe<ID> + ?Sized,
450-
{
451-
}
452-
453-
// This is to allow `ListArc<U>` to be dispatched on when `ListArc<T>` can be coerced into
454-
// `ListArc<U>`.
455-
impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc<T, ID>
456-
where
457-
T: ListArcSafe<ID> + Unsize<U> + ?Sized,
458-
U: ListArcSafe<ID> + ?Sized,
459-
{
460-
}
446+
/// `ListArc` is well-behaved so that its dereferencing operation does not mutate.
447+
unsafe impl<T: ?Sized + ListArcSafe<ID>, const ID: u64> PinCoerceUnsized for ListArc<T, ID> {}
461448

462449
/// A utility for tracking whether a [`ListArc`] exists using an atomic.
463450
///

rust/kernel/sync/arc.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626
use core::{
2727
alloc::Layout,
2828
fmt,
29-
marker::{PhantomData, Unsize},
29+
marker::{CoercePointee, PhantomData},
3030
mem::{ManuallyDrop, MaybeUninit},
3131
ops::{Deref, DerefMut},
3232
pin::Pin,
@@ -125,6 +125,8 @@ mod std_vendor;
125125
/// let coerced: Arc<dyn MyTrait> = obj;
126126
/// # Ok::<(), Error>(())
127127
/// ```
128+
#[repr(transparent)]
129+
#[derive(CoercePointee)]
128130
pub struct Arc<T: ?Sized> {
129131
ptr: NonNull<ArcInner<T>>,
130132
_p: PhantomData<ArcInner<T>>,
@@ -170,13 +172,6 @@ impl<T: ?Sized> ArcInner<T> {
170172
}
171173
}
172174

173-
// This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the
174-
// dynamically-sized type (DST) `U`.
175-
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
176-
177-
// This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`.
178-
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
179-
180175
// SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because
181176
// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
182177
// `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` using a
@@ -471,18 +466,13 @@ impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {
471466
/// obj.as_arc_borrow().use_reference();
472467
/// # Ok::<(), Error>(())
473468
/// ```
469+
#[repr(transparent)]
470+
#[derive(CoercePointee)]
474471
pub struct ArcBorrow<'a, T: ?Sized + 'a> {
475472
inner: NonNull<ArcInner<T>>,
476473
_p: PhantomData<&'a ()>,
477474
}
478475

479-
// This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
480-
// `ArcBorrow<U>`.
481-
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
482-
for ArcBorrow<'_, T>
483-
{
484-
}
485-
486476
impl<T: ?Sized> Clone for ArcBorrow<'_, T> {
487477
fn clone(&self) -> Self {
488478
*self

samples/rust/rust_print.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,25 @@ fn arc_print() -> Result {
3434
// Uses `dbg` to print, will move `c` (for temporary debugging purposes).
3535
dbg!(c);
3636

37+
// `Arc` can be used to delegate dynamic dispatch and the following is an example.
38+
// Both `i32` and `&str` implements `Display`.
39+
// This enables us to express a unified behaviour, contract or protocol on both `i32` and `&str`
40+
// in a single `Arc` type `Arc<dyn Display>`.
41+
let a_i32_display: Arc<dyn Display> = Arc::new(42i32, GFP_KERNEL)?;
42+
let a_str_display: Arc<dyn Display> = a.clone();
43+
arc_dyn_print(&a_i32_display);
44+
arc_dyn_print(&a_str_display);
45+
3746
// Pretty-prints the debug formatting with lower-case hexadecimal integers.
3847
pr_info!("{:#x?}", a);
3948

4049
Ok(())
4150
}
4251

52+
fn arc_dyn_print(arc: &Arc<dyn Display>) {
53+
pr_info!("Arc<dyn Display> says {arc}");
54+
}
55+
4356
impl kernel::Module for RustPrint {
4457
fn init(_module: &'static ThisModule) -> Result<Self> {
4558
pr_info!("Rust printing macros sample (init)\n");

0 commit comments

Comments
 (0)