Skip to content

Commit 27e8103

Browse files
gating behind version 1.83.0
1 parent 54c00aa commit 27e8103

File tree

5 files changed

+77
-21
lines changed

5 files changed

+77
-21
lines changed

init/Kconfig

+3
Original file line numberDiff line numberDiff line change
@@ -1964,6 +1964,9 @@ config RUST
19641964

19651965
If unsure, say N.
19661966

1967+
config RUST_COERCE_POINTEE
1968+
def_bool y if RUSTC_VERSION >= 108300
1969+
19671970
config RUSTC_VERSION_TEXT
19681971
string
19691972
depends on RUST

rust/kernel/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
1414
#![no_std]
1515
#![feature(arbitrary_self_types)]
16-
#![feature(coerce_unsized)]
17-
#![feature(derive_coerce_pointee, pin_coerce_unsized_trait)]
16+
#![cfg_attr(
17+
CONFIG_RUST_COERCE_POINTEE,
18+
feature(derive_coerce_pointee, pin_coerce_unsized_trait)
19+
)]
20+
#![cfg_attr(not(CONFIG_RUST_COERCE_POINTEE), feature(coerce_unsized, unsize))]
1821
#![feature(inline_const)]
1922
#![feature(lint_reasons)]
20-
#![feature(unsize)]
2123

2224
// Ensure conditional compilation based on the kernel configuration works;
2325
// otherwise we may silently break things like initcall handling.

rust/kernel/list/arc.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub use impl_list_arc_safe;
160160
///
161161
/// [`List`]: crate::list::List
162162
#[repr(transparent)]
163-
#[derive(CoercePointee)]
163+
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(CoercePointee))]
164164
pub struct ListArc<T, const ID: u64 = 0>
165165
where
166166
T: ListArcSafe<ID> + ?Sized,
@@ -443,7 +443,28 @@ where
443443
}
444444
}
445445

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

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

rust/kernel/sync/arc.rs

+26-5
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ use crate::{
2323
try_init,
2424
types::{ForeignOwnable, Opaque},
2525
};
26+
#[cfg(CONFIG_RUST_COERCE_POINTEE)]
27+
use core::marker::CoercePointee;
28+
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
29+
use core::marker::Unsize;
2630
use core::{
2731
alloc::Layout,
2832
fmt,
29-
marker::{CoercePointee, PhantomData},
33+
marker::PhantomData,
3034
mem::{ManuallyDrop, MaybeUninit},
3135
ops::{Deref, DerefMut},
3236
pin::Pin,
@@ -125,8 +129,8 @@ mod std_vendor;
125129
/// let coerced: Arc<dyn MyTrait> = obj;
126130
/// # Ok::<(), Error>(())
127131
/// ```
128-
#[repr(transparent)]
129-
#[derive(CoercePointee)]
132+
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, repr(transparent))]
133+
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(CoercePointee))]
130134
pub struct Arc<T: ?Sized> {
131135
ptr: NonNull<ArcInner<T>>,
132136
_p: PhantomData<ArcInner<T>>,
@@ -172,6 +176,15 @@ impl<T: ?Sized> ArcInner<T> {
172176
}
173177
}
174178

179+
// This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the
180+
// dynamically-sized type (DST) `U`.
181+
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
182+
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}
183+
184+
// This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`.
185+
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
186+
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}
187+
175188
// SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because
176189
// it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs
177190
// `T` to be `Send` because any thread that has an `Arc<T>` may ultimately access `T` using a
@@ -466,13 +479,21 @@ impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {
466479
/// obj.as_arc_borrow().use_reference();
467480
/// # Ok::<(), Error>(())
468481
/// ```
469-
#[repr(transparent)]
470-
#[derive(CoercePointee)]
482+
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, repr(transparent))]
483+
#[cfg_attr(CONFIG_RUST_COERCE_POINTEE, derive(CoercePointee))]
471484
pub struct ArcBorrow<'a, T: ?Sized + 'a> {
472485
inner: NonNull<ArcInner<T>>,
473486
_p: PhantomData<&'a ()>,
474487
}
475488

489+
// This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into
490+
// `ArcBorrow<U>`.
491+
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
492+
impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>
493+
for ArcBorrow<'_, T>
494+
{
495+
}
496+
476497
impl<T: ?Sized> Clone for ArcBorrow<'_, T> {
477498
fn clone(&self) -> Self {
478499
*self

samples/rust/rust_print.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,34 @@ 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);
37+
#[cfg(CONFIG_RUST_COERCE_POINTEE)]
38+
{
39+
use core::fmt::Display;
40+
fn arc_dyn_print(arc: &Arc<dyn Display>) {
41+
pr_info!("Arc<dyn Display> says {arc}");
42+
}
43+
// `Arc` can be used to delegate dynamic dispatch and the following is an example.
44+
// Both `i32` and `&str` implements `Display`.
45+
// This enables us to express a unified behaviour, contract or protocol on both `i32` and `&str`
46+
// in a single `Arc` type `Arc<dyn Display>`.
47+
let a_i32_display: Arc<dyn Display> = Arc::new(42i32, GFP_KERNEL)?;
48+
let a_str_display: Arc<dyn Display> = a.clone();
49+
arc_dyn_print(&a_i32_display);
50+
arc_dyn_print(&a_str_display);
51+
}
52+
53+
#[cfg(not(CONFIG_RUST_COERCE_POINTEE))]
54+
pr_info!(
55+
"The demonstration for dynamic dispatching through Arc is skipped. "
56+
"To see the print-out from this example, please upgrade your Rust compiler to 1.83.0 or higher.\n"
57+
);
4558

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

4962
Ok(())
5063
}
5164

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

0 commit comments

Comments
 (0)